bash:エコー:書き込みエラー:システムコールが中断されました。

bash:エコー:書き込みエラー:システムコールが中断されました。

00000000から99999999までの8桁の数字をすべて含むソートされたリストを作成したいと思います。私はシェルに次のように入力しました:

f() {
 while IFS="" read -r line; do
   for i in {0..9}; do 
       echo "$line$i";
   done;
 done
}

echo | f | f | f | f | f | f | f | f | tee result.txt | wc -l

答えは次のとおりです

bash: echo: write error: Interrupted system call
bash: echo: write error: Interrupted system call
bash: echo: write error: Interrupted system call
99998890

これらの3つのエラーと間違ったresult.txtが表示されるのはなぜですか?

私は使う

GNU bash、バージョン 4.4.12(1)-リリース(x86_64-pc-linux-gnu)

Debian GNU/Linux 9.6(拡張)

Linuxカーネル: 4.19.0 #2 SMP Thu Nov 1 15:31:34 EET 2018 x86_64 GNU/Linux

答え1

write error: Interrupted system callスクリプトの実行中にコンソールウィンドウのサイズを変更すると、特定のエラーが生成されます。

何かを作る:

 trap '' SIGWINCH

それを避けます。

参考にしてください

 seq 99999999 >result.txt; wc -l <result.txt

より速く、このSIGWINCH問題を回避できます。

答え2

これは本当のバグです。[1]in bash、これはonだけでなく、SIGWINCHトラップが設定されているすべての信号でも発生します。

{ pid=$BASHPID; trap : USR1; (sleep 1; kill -USR1 $pid) &
         printf %0100000d 1; } | sleep 3600
bash: printf: write error: Interrupted system call

これは、a)シグナルハンドラ(ハンドラーを除く)bashを設定するか、b)組み込み関数を呼び出すときにシグナルハンドラを処理できなかったために発生します。SA_RESTARTSIGCHLDEINTRwrite()printfecho

EINTR(「中断されたシステムコール」)は、エラー状態を示す方法ではなく、プログラマがブロックの読み取り/書き込みなどをメインループの信号処理と組み合わせることを可能にする方法です。絶対ユーザーに流出してはいけません。

このエラーはあまり頻繁には発生しません。条件を正しく設定するのは素晴らしいことですwrite()組み込み(外部コマンドを介してではない)パイプバッファを埋める必要があります(もう一方の端にあるリーダーはたくさんパイプから読み取る速度が遅い、またはまったく読み込まれないしかし、まだ生きている)スクリプトはトラップを使用するか、端末ウィンドウのサイズを変更する必要があります。

そして実装アーティファクトが異なるため、これは中断されたwrite()sread()やsではなく中断されたopen()sにのみ影響します(たとえば、open()名前付きパイプ/ fifosブロック)。

[1]このフォームはすでに存在します。レポート電子。

関連情報