"watch"コマンドを使用して引用符(")を含む複数のコマンドを囲むには?

watch次のコマンドチェーンを使用したいと思います。

journalctl | grep 'UFW BLOCK' | grep 'DST=192.168.0.2' | awk '{printf "%-4s%-3s%-10s%-1s%+16s\n", $1, $2, $3, $7, $11, $18, $19}'

watch通常、コマンドシステムに適用したい場合は、コマンドシステムを引用符で囲みます。

watch "COMMAND_1 | COMMAND_2 | ... | COMMAND_n"

しかし、上記のコマンドの1つに別の引用符があると問題が発生します。この問題に対する解決策は何ですか?

ベストアンサー1

引用の心配を避けるために、次の文書を使用してください。

shell_code=$(cat << 'EOF'
  journalctl |
    awk '
      /UFW BLOCK/ && index($0, "DST=192.168.0.2 ") {
         printf "%-4s%-3s%-10s%-1s%+16s\n", $1, $2, $3, $7, $11, $18, $19
      }'
EOF
)

watch "$shell_code"

(または実装がまだコマンドラインを解釈するためにシェルを起動せずに代わりにコマンド自体を実行しているwatch sh -c "$shell_code"場合、最近ではこれらの実装はますますまれになっています。)watchwatch

その他の注意事項:

  • awkできることのほとんどを実行できるgrepため、互いに接続する必要はほとんどありません。

  • .単一文字に一致する正規表現演算子です。正規表現の一致を使用する代わりに、orを使用してエスケープしたり、inまたはinを使用して部分文字列検索を実行したりgrep 192.168.0.2でき192.168.012ます。[.]\.-Fgrepindex()awk

  • 検索文字列に余分なスペースを追加しない場合は、DST=192.168.0.2次の項目もありますDST=192.168.0.234。使用すると、grep -Fw DST=192.168.0.2両方の問題が解決されます。

  • $sまたはsをエスケープするのを忘れてコマンドインジェクションの脆弱性が発生しやすいため、シェルコードを囲むために二重引用符を使用しないでください`(変数の内容がシェルコードとして解釈される可能性があります)。一重引用符には特殊文字は含まれていないため、より安全です。これにはs自体が含まれているため'(少なくともBourneのようなシェルでは)'sには含めることはできませんが、常にで連結され(バックスラッシュで引用)'...'として入力できます。だからここにあります:'foo'\''bar''foo'\'''bar'

    watch 'journalctl |
       awk '\''
         /UFW BLOCK/ && index($0, "DST=192.168.0.2 ") {
            printf "%-4s%-3s%-10s%-1s%+16s\n", $1, $2, $3, $7, $11, $18, $19
         }'\'
    
  • journalctl新しいログエントリが到着すると、それを表示する-f/モードがあります。--followログ全体を繰り返し検索する代わりに、この方法を使用できます。


1Runの実装は引数が空白watchで連結されたコードを解釈しますが、/オプションを使用してコマンドを直接実行することができるため、他の言語ソルバー(たとえば、または)でコードをより簡単に解釈できます。procps-ngsh-x--execwatch -x zsh -c 'zsh code'watch -x perl -e 'perl code'

²ただし、完全性のためにこのオプションが有効になっている場合、zsh(Bourneに似ていますが、rcおよびcsh機能もあります)は、単一引用符で囲まれた'foo''bar'文字列内に単一引用符を含めることができます。rcrcquotes

おすすめ記事