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_RESTART
SIGCHLD
EINTR
write()
printf
echo
EINTR
(「中断されたシステムコール」)は、エラー状態を示す方法ではなく、プログラマがブロックの読み取り/書き込みなどをメインループの信号処理と組み合わせることを可能にする方法です。絶対ユーザーに流出してはいけません。
このエラーはあまり頻繁には発生しません。条件を正しく設定するのは素晴らしいことですwrite()
。組み込み(外部コマンドを介してではない)パイプバッファを埋める必要があります(もう一方の端にあるリーダーはたくさんパイプから読み取る速度が遅い、またはまったく読み込まれないしかし、まだ生きている)スクリプトはトラップを使用するか、端末ウィンドウのサイズを変更する必要があります。
そして実装アーティファクトが異なるため、これは中断されたwrite()
sread()
やsではなく中断されたopen()
sにのみ影響します(たとえば、open()
名前付きパイプ/ fifosブロック)。
[1]このフォームはすでに存在します。レポート電子。