バイナリを実行する関数を定義しましょう。
function execute() { ./binary; }
次に、テキストファイルを最初の関数にパイプする2番目の関数を定義します。
function test() { cat in.txt | execute; }
binary
segfaultと競合する場合、test
CLIから呼び出すと戻りコードが発生します139
が、「segfault」エラーは端末に印刷されません。
直接呼び出しを定義すると、test
「セグメントエラー」が出力されます。binary
function test() { cat in.txt | ./binary; }
stdin を入力せずに呼び出しを定義すると、execute
次のように印刷されます。
function test() { execute; }
in.txt
最後にパイプを通さずに直接リダイレクトする場合execute
にも印刷されます。
function test() { execute <in.txt; }
これは Bash 4.4 でテストされました。なぜそんなことですか?
答え1
この診断メッセージは対話型シェルによって生成されます。職業管理システムは、ユーザーの利益のために基本プログラムがクラッシュしたために発生しません。シェル関数をパイプするときサブシェル関数を実行するために作成され、サブシェルはユーザー側とは見なされません。関数が正常に呼び出されると、元のシェルで実行され、メッセージが印刷されます。
現在のシェルでジョブ制御を無効にすることでこれをテストできます。
set +m
その後、./binary
もう一度実行してください。今何も印刷されません。ジョブ制御の再活動化を使用してくださいset -m
。
単純なサブシェルでも同じ効果があります。
( : ; ./binary )
診断情報は印刷されません(サブシェル除去の最適化を防ぐために2つのコマンドが必要です)。管路出るこの関数も同じことをします。
ジョブ制御はサブシェルで無効になり、手動で有効にしても静かになります。これはシステムの不幸な欠陥です。非対話型シェルでは、メッセージは対話型シェルの他のすべての場所にあるため、常に異なるメカニズムを介して報告されます。
診断内容を印刷することが重要な場合は、関数の代わりにスクリプトを作成して、その内容を常に含めることができます。パイプラインで関数を使用しているため、とにかく関数が必要な操作を実行できないため、これを行うにはかなりの費用がかかりません。
私はこれが間違いだと言いたくありません。このように振る舞う一つの考えられる理由は次のとおりです。コマンドの置き換え$(...)
サブシェルも実行するのは適切に機能します。
foo=$(echo|test)
foo
パイプラインエラーが原因でnull拡張が発生するように診断メッセージを保存しないでください。別のアプローチは、意図的に診断メッセージを一時的に表示しないことです。