web-dev-qa-db-ja.com

awkからawkへの配管を回避する方法は?

次のスクリプトを作成しました。このスクリプトは、ユーザーのcrontabから実行され、SSHポートフォワードの~/.ssh/configを解析し、-VARIABLE--行が「remote」、「local、」で終わる場合は自動的に接続します。 「または「動的」。

~/.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

正常に動作しますが、port=行のHostコマンドを組み合わせて、あるawkを別のawkにパイプする必要がないようにすることができるかどうか疑問に思いました。数時間遊んで構文を理解しようとした後、私はそれをいじくり回していません。

autosshが存在し、私が行っていることを実行するためのより良い方法であることは知っていますが、これは学習体験であり、パッケージをインストールせずに同じタスクを実行しようとします。

3
Q23

1回の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
}

これは、「Host」ステートメントを検出するたびにホストを格納し、有効なホストが定義されているときに検出され、受け入れられた「Forward」ステートメントの1つと一致する行に、ターゲットポートを取得し、コロンの前にある部分を削除します。ホストとポートを出力します。

localsocksdynamic 8080
localwebserverremote 8080
indirectaccesslocal 2222

次に、これはwhilereadループに送られ、ポートをチェックしてSSHを実行します。

3
Stephen Kitt