Shell-Script
如何避免管道 awk 到 awk?
我編寫了以下腳本,它從我的使用者執行
crontab
,解析~/.ssh/config
SSH 埠轉發,如果Host
行以“遠端”、“本地”或“動態”結尾,則自動連接它們。範例
~/.ssh/config
塊:Host localsocksdynamic DynamicForward 8080 Hostname 1.2.3.4 Host localwebserverremote RemoteForward *:8080 localhost:80 Hostname 1.2.3.4 Host indirectaccesslocal LocalForward 2222 2.3.4.5:80 Hostname 1.2.3.4
腳本:
#!/bin/sh port_forwards=$(awk '/Host .*(remote|local|dynamic)/{printf $2} " "}' ~/.ssh/config for forward in ${port_forwards} do port=$(awk "/${forward}/{f=1;next}/Host /{f=0}f" ~/.ssh/config | awk '/(Remote|Local|Dynamic)Forward/{print $2}' | cut -d':' -f2) [ -z ${port} ] || nc -z 127.0.0.1 ${port} || ssh -fqN ${forward} > /dev/null 2>&1 done
它工作得很好,但我想知道是否可以將
awk
命令port=
行中的命令組合起來,這樣就不必將一個管道awk
連接到另一個管道。在玩了幾個小時並試圖理解語法之後,我只是不理解它。我知道
autossh
存在並且是一種更好的方式來做我正在做的事情,但這是一種學習體驗,並嘗試在不安裝軟體包的情況下完成相同的任務。
您可以通過單個 AWK 呼叫執行所有文本處理,因為您只關心轉發,所以簡化了:
#!/bin/sh awk '/^Host / { host = $2 } host && /(Remote|Local|Dynamic)Forward/ { port=$2; gsub(".*:", "", port); print host, port }' ~/.ssh/config | while read host port; do nc -z 127.0.0.1 "${port}" || ssh -fqN "${host}" > /dev/null 2>&1 done
寫得更清晰,AWK 腳本是
/^Host / { host = $2 } host && /(Remote|Local|Dynamic)Forward/ { port=$2; gsub(".*:", "", port); print host, port }
每當它看到“主機”語句時,都會儲存主機,然後在定義有效主機時遇到的行上儲存主機,並匹配接受的“轉發”語句之一,檢索目標埠,如果有冒號前的部分,則刪除,以及輸出主機和埠:
localsocksdynamic 8080 localwebserverremote 8080 indirectaccesslocal 2222
然後將其輸入
while
read
循環以檢查埠並執行 SSH。