.png)
コマンドをパイプし、スクリプト内でパイプを切断するかどうかを決定するにはどうすればよいでしょうか。
それはこの質問しかし、代わりにawk
独自のスクリプトを使用したいと思います。
check_ip | update_bind9
check_ip
外部 IP ( curl -s ifconfig.co
) を見つけて、それをファイルに保存されている IP ( ~/.ip
) と比較します。
主な質問は次のとおりです。
IP が変更された場合は、check_ip
IP をパイプに渡す必要があります。変更されていない場合は、パイプを切断する必要があります。
check_ip
それはパイプを壊しますか、それともupdate_bind9
IP で呼び出されない場合は呼び出しを無視しますか?
いくつかテストを行ってみましたcheck_ip | echo "ok"
。
exit 0
、、、exit 1
を試しましたreturn true
。return false
を試しましたset -e
。 成功しませんでした。
答え1
パイプラインのすべてのコンポーネント同時に開始する– 最初のコマンドで何が起こっても、2 番目のコマンドは常に開始されます。
したがって、空の stdin を処理する必要があるのは 2 番目のコマンドです。
しかし、そもそもパイプはこれには適していないと思います。
(おそらく|
(パイプ)と||
(ブールOR)を混同しているのではないでしょうか?後者ははif/then の短縮版としてよく使用されます。たとえば、x || y
x が失敗した場合にのみ y を呼び出します。同様に、x && y
x が成功した場合にのみ 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
その後:
foo=$(command1)
は、出力から末尾の改行をすべて削除しますcommand1
。その後echo "$foo"
(またはprintf … "$foo"
) は、正確に 1 つの改行文字 (またはそれぞれ固定数の改行文字) を追加します。このため、command2
からの正確な出力が得られない可能性がありますcommand1
。command1
NUL 文字を含む出力が生成される場合があります。Bash は変数に NUL を保存できません (ほとんどのシェルは保存できませんが、zsh は保存できます)。NUL が表示された場合、command2
は からの正確な出力を取得できませんcommand1
。command1
巨大なストリーム、あるいは無限のストリームが生成される可能性があるため、それを変数に格納することはできない可能性があります。
変数の代わりにファイルを使用すると、最後の問題を除くすべての問題が解決されます。command1 | ifne command2
は、3 つの問題すべての影響を受けません。