Shell-Script

如何避免管道 awk 到 awk?

  • June 8, 2017

我編寫了以下腳本,它從我的使用者執行crontab,解析~/.ssh/configSSH 埠轉發,如果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。

引用自:https://unix.stackexchange.com/questions/369846