bash の条件付きパイプ (カスタム スクリプト)

bash の条件付きパイプ (カスタム スクリプト)

コマンドをパイプし、スクリプト内でパイプを切断するかどうかを決定するにはどうすればよいでしょうか。

それはこの質問しかし、代わりにawk独自のスクリプトを使用したいと思います。

check_ip | update_bind9

check_ip外部 IP ( curl -s ifconfig.co) を見つけて、それをファイルに保存されている IP ( ~/.ip) と比較します。

主な質問は次のとおりです。

IP が変更された場合は、check_ipIP をパイプに渡す必要があります。変更されていない場合は、パイプを切断する必要があります。

check_ipそれはパイプを壊しますか、それともupdate_bind9IP で呼び出されない場合は呼び出しを無視しますか?

いくつかテストを行ってみましたcheck_ip | echo "ok"

exit 0、、、exit 1を試しましたreturn truereturn falseを試しましたset -e。 成功しませんでした。

答え1

パイプラインのすべてのコンポーネント同時に開始する– 最初のコマンドで何が起こっても、2 番目のコマンドは常に開始されます。

したがって、空の stdin を処理する必要があるのは 2 番目のコマンドです。


しかし、そもそもパイプはこれには適していないと思います。

(おそらく|(パイプ)と||(ブールOR)を混同しているのではないでしょうか?後者はif/then の短縮版としてよく使用されます。たとえば、x || yx が失敗した場合にのみ y を呼び出します。同様に、x && yx が成功した場合にのみ y を呼び出します。

一般的には、if/then ブロックを使用する必要があります。たとえば、check_ipアドレスが異なる場合は 0 (成功) を返し、アドレスが同じ場合は 1 (失敗) を返す場合は、次のようになります。

if addr=$(check_ip); then
    echo "$addr" | update_bind9
fi

あるいは、update_bind9 が独自に (stdin を読み取らずに) アドレスを決定できる場合は、次のようになります。

if check_ip_needs_updating; then
    update_bind9
fi

答え2

この他の答えは良いです。しかし、条件付きでパイプする必要がある場合は、ifne役に立つ:

ifne標準入力が空でない場合にのみ、次のコマンドを実行します。

あなたの場合は次のようになりますcheck_ip | ifne update_bind9

ifneデフォルトでは Linux にインストールされていない可能性が高いです。私の Debian 10 ではパッケージに含まれています。上記の回答のように、出力を変数にmoreutils保存して条件に応じて再利用できるため、余分なツールはまったく過剰であると思われるかもしれません。check_ip

if addr=$(check_ip); then
    echo "$addr" | update_bind9
fi

条件は[ -n "$addr" ]など何でも構いません。重要なのは、変数を使用することです。上記のようなコードで問題は解決するかもしれませんが、一般的には少なくとも 3 つの問題があります。command1 | command2の代わりに と仮定しますcheck_ip | update_bind9。解決策は次のように一般化されます。

if foo=$(command1); then
    echo "$foo" | command2
fi

その後:

  1. foo=$(command1)は、出力から末尾の改行をすべて削除しますcommand1。その後echo "$foo"(またはprintf … "$foo") は、正確に 1 つの改行文字 (またはそれぞれ固定数の改行文字) を追加します。このため、command2からの正確な出力が得られない可能性がありますcommand1

  2. command1NUL 文字を含む出力が生成される場合があります。Bash は変数に NUL を保存できません (ほとんどのシェルは保存できませんが、zsh は保存できます)。NUL が表示された場合、command2は からの正確な出力を取得できませんcommand1

  3. command1巨大なストリーム、あるいは無限のストリームが生成される可能性があるため、それを変数に格納することはできない可能性があります。

変数の代わりにファイルを使用すると、最後の問題を除くすべての問題が解決されます。command1 | ifne command2は、3 つの問題すべての影響を受けません。

関連情報