web-dev-qa-db-ja.com

複雑なシェルコマンドをSSHで渡してリモートで実行するにはどうすればよいですか?私は構文エラーを投げるか、ローカルで解釈されます!

システムにいっぱいになっている(> = 70%いっぱい)ディスクがあるかどうかを確認する次のようなコマンドがあります。

if [[ -n df -PTh|column -t|awk '{print $6 $7}'|awk -F"%" '{printf "%-9s %-5s\n",$1,$2}'|grep -v -e "Use" -e "Mounted"|awk '$1>70{printf "%-9s %-5s\n",$1,$2}' ]]; then echo "not present"; else echo ">70 is present"; fi

SSHを使用してリモートサーバーで上記のコマンドを実行したいと思います。何かのようなもの:

ssh remoteserver "if [[ -n df -PTh|column -t|awk '{print $6 $7}'|awk -F"%" '{printf "%-9s %-5s\n",$1,$2}'|grep -v -e "Use" -e "Mounted"|awk '$1>70{printf "%-9s %-5s\n",$1,$2}' ]]; then echo "not present"; else echo ">70 is present"; fi"

しかし、私がそれを試みたとき、私は次のエラーを受け取りました:

Host: remoteserver bash: -c: line 0: syntax error in conditional expression bash: -c: line 0: syntax error near /home'
bash: -c: line 0:if [[ -n 92 /home'
3
user275225

まず、awk/grep/awk/grep/awk/grep/etcステートメントの戦争犯罪を次のように減らします。

df | awk '$5~/([7-9]|10)[0-9]/'

出力を確認するために必要なすべてを行います。 reallyきれいな出力が必要であるが、確認するだけならifがあれば、{print ...}句をawkステートメントに追加できます。が出力されるので、これについては合理的にしましょう。

If/elseも短縮できます。また、方向を修正しました-あなたの方向は逆転しました。コマンド全体は次のようになります。

[[ -n $(df | awk '$5~/([7-9]|10)[0-9]/') ]] && echo 'ACHTUNG!' || echo 'No >=70s'

あなたはそれがただわずかにより啓発的であることに同意すると思います。

これでおそらくこれを手動でエスケープしてbash -c "..."でラップすることができますが、その楽しみはどこにありますか?代わりに、コマンドをローカルファイル(commands.txtなど)に保存し、次のようにサーバーに送信します。

ssh user@Host $(<commands.txt)

そして、そこに置いておくこともできます。実際に、元のコマンドの動作バージョンをそこに投げ入れて送信することができます。このことは非常に堅牢です...しかし、私たちはそれをしたくありません...コマンドでより賢く(そしてチート)、ifブラケット(エスケープの問題を引き起こすもの)をなくすことができるときではありません)。

現在、dfをリモートで実行し、リモートで処理しています。それをする必要はありません。 sshdfを実行させてから、出力をローカルで処理できます。これは即座にエスケープの問題を解決しますが、現在、書き換えが少しくなるロジック[[ブラケット]]に縛られています。

[[ -n $(ssh user@Host df | awk '$5~/([7-9]|10)[0-9]/') ]] && .......

うん.
私たちはそれよりも優れています。
前に踏みつけた猿や類人猿とは異なり、終了コードがあります。

何かの実行が終了すると、コードを返すことができます。これらのコードは さまざまなもの を意味しますが、一般的に0は「私が意図したとおりにした」ことを意味し、それ以上は「悪いことをした、Bawss」を意味します。

&&||などの条件付きフックは、それらに入力される終了コードを参照して、実行するかどうかを決定します。この場合、awkにゼロ以外の方法で終了するように指示すると、コードフローを制御できるようになります。

ssh user@Host df | awk '$5~/([7-9]|10)[0-9]/ {exit 1}' && echo 'No >=70s' || echo 'ACHTUNG!'

これは、最初の> = 70の値を検出するとすぐに終了することも意味します。数百万台のドライブがある場合、他の主要ブランドのスクリプトよりもseconds節約できます。はい、この最終バージョンで何が起こっているかを再確認するために:

  1. サーバーに接続し、dfをリモートで実行しています
  2. 出力は、awkのローカルインスタンスにパイプで戻されます
  3. awkは、5番目の列が70〜100に一致する正規表現に一致するかどうかを確認します
  4. 存在する場合、コード1を終了し、||コードが実行されます(is 70%を超えるドライブが使用されています)
  5. そうでない場合、コード0を終了し、&&コードが実行されます。

以前のリビジョンでは、awkステートメントでNR>1チェックも行っていましたが、5番目の列の値を明示的にチェックしている(そして、それが機能する数字である)ので、安全に省略できますそれも。

8
Oli