set -eu
VAR=$(zcat file.gz | head -n 12)
は失敗で終了する細かいbashのzcatヘッドでパイプが破損しますか?
set -eu -o pipefail
VAR=$(zcat file.gz | head -n 12)
原因はbashを動作します。 これはどのようにパイプパイプを引き起こしていますか?
file.gzには数百万行(〜750 MB、圧縮済み)のファイルが含まれています。
set -eu
VAR=$(zcat file.gz | head -n 12)
は失敗で終了する細かいbashのzcatヘッドでパイプが破損しますか?
set -eu -o pipefail
VAR=$(zcat file.gz | head -n 12)
原因はbashを動作します。 これはどのようにパイプパイプを引き起こしていますか?
file.gzには数百万行(〜750 MB、圧縮済み)のファイルが含まれています。
考えてみてください。
head
と書きます。head
を終了するように指示しています。 あなたはエラーを持っている:zcat
はその先のパイプラインが早期に閉鎖され、正常に入力ファイルの解凍バージョンを書くことができませんでした!これは、これが誤った何かを介して、ユーザーの意図によるものであることを知る方法を持っていません。
ディスクに書き込むためにzcat
を使用していて、ディスク領域が不足していたり、ネットワークストリームに繋がっていて接続が切断された場合は、完全に正しいものであり、失敗を示すステータス。これはそのルールの単なる別のケースです。
zcat
は、オペレーティングシステムによって与えられている特定のエラーは、次の条件でwrite
システムコールによって返された、EPIPE
である:試みはいずれかによって読み取りのためにオープンされていないパイプに書き込むようになされますプロセス。 head
(このFIFOの唯一のリーダー)の後
バグあろうEPIPEを返すためにパイプラインないの入力側への書き込みのため、終了しました。 zcat
がその出力を書き込むエラーを黙って無視し、このイベントを反映する終了ステータスなしで不正確な出力ストリームを生成できるようにするには、同様にがバグになります。
あなたが考慮するかもしれない1つの回避策は、プロセス置換を使用している、方法によって、あなたのシェルのいずれかのオプションを変更したくない場合:この場合
var=$(head -n 12 < <(zcat file.gz))
、zcat
ではありませんパイプラインコンポーネントであり、その終了ステータスは成功を判断するために考慮されません。 (独立した成功/失敗の判定が必要な場合は、$var
が12行であるかどうかをテストすることができます)。
優れた答え!詳細をありがとうございます。これらのことは、訓練を受けたコンピュータプログラマーや経験豊富なコーダーにとっては明らかですが、コンピュータ科学者ではないスクリプトやコードを書く多くの人が多く、私たちの多くは独学です。現実には、私たちの多くは、アマチュアの多くが、バッシュ、パイプ、ストリーム、システムコールなどの内部の仕組みを掘り起こす方法や知識がないということさえあります。ストリームの詳細を理解できないときは、 '書き込み'など)は、 '頭部 'がファイルストリームを適切に終わらせるという純粋な想像力によって考えられる。 – cmo
さて、 'set -e'と' set -u'は両方とも...親切に置くために... *議論の余地があります。 POSIXで指定されていない詳細をリリース間での動作に変更するようにしました)。[BashFAQ#105](http://mywiki.wooledge.org/BashFAQ/105)および[BashFAQ#112](http://mywiki.wooledge.org/BashFAQ/112)に記載されているすべてのシナリオを理解していない限り、テストすることができないbashリリースとの互換性は必要ありません。その使用を再考するかもしれません。 http://shellcheck.net/での静的な確認では、警告が少なくなります。 –
(これとは対照的に、 'pipefail'は一般的には良いアイデアです;パイプラインコンポーネントが失敗するような特定のケースがある場合は、明示的に許可することができます(この場合、' var = $ {{zcat file。 gz || :;} | head -n 12) 'を実行します)。 –
...脇に:小文字の 'var'は正しいです。 [POSIX環境変数仕様書](http://pubs.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap08.html)の命名規則を参照してください。すべての大文字の名前は、シェルまたはシステムにとって意味を持つ変数によって使用されます。小文字の名前はアプリケーション用に予約されています。これは、シェル変数を設定すると、同様の名前の環境変数を上書きするため、非エクスポートシェル変数にも適用されます。 –