bash: echo: write error: Panggilan sistem terputus

9

Saya ingin membuat daftar yang diurutkan dengan semua angka 8-digit - dari 00000000 hingga 99999999. Saya mengetikkan shell:

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

jawabannya adalah

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

Mengapa saya mendapatkan ketiga kesalahan ini dan result.txt salah bentuk?

saya menggunakan

GNU bash, versi 4.4.12 (1) -release (x86_64-pc-linux-gnu)

Debian GNU / Linux 9.6 (peregangan)

Kernel Linux: 4.19.0 # 2 SMP Kamis 1 Nov 15:31:34 EET 2018 x86_64 GNU / Linux

hon
sumber
2
Saya tidak bisa menahan perasaan bahwa cara melakukannya tidak akan lebih efisien daripada seq -w 0 99999999.
Kusalananda
1
Maka pertanyaannya adalah tidak lengkap / tidak benar / ditulis dengan buruk atau sesuatu yang lain. Karena skrip (ketika selesai dengan }) berfungsi dengan benar. @ GAD3R
Isaac
1
Catatan: Saya dapat memicu kesalahan ini hampir sesuai permintaan. Mereka sering muncul ketika saya mengubah ukuran konsolejendela saya . Mengubah ukuran seperti itu hampir cukup dalam kasus saya, namun tidak perlu.
Kamil Maciorowski
Saya dapat menghapus | tee result.txt, dan masih mendapatkan kesalahan.
ctrl-alt-delor
Catatan lain: executable eksternal ( /bin/echodalam kasus saya) bukannya echobuiltin membuat fungsi kebal (atau setidaknya kurang rentan) untuk masalah ini.
Kamil Maciorowski

Jawaban:

6

write error: Interrupted system callKesalahan spesifik dihasilkan ketika ukuran jendela konsol diubah saat skrip dieksekusi.

Melakukan:

 trap '' SIGWINCH

akan menghindarinya.

Perhatikan bahwa a

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

Akan lebih cepat dan akan menghindari SIGWINCHmasalah.

Ishak
sumber
5
Jadi apa yang terjadi? Mengapa saya tidak pernah melihat ini sebelumnya? Mengapa kesalahan tulis, hal yang benar untuk dilakukan?
ctrl-alt-delor
4

Ini sebenarnya adalah bug [1] di bash, dan itu tidak terjadi hanya pada SIGWINCH, tetapi juga pada sinyal yang perangkap ditetapkan:

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

Hal ini terjadi karena bashgagal baik) mengatur penangan sinyal dengan SA_RESTART(kecuali untuk SIGCHLDhandler), atau b) menangani EINTRsaat memanggil write()dalam printfdan echobuiltin.

EINTR("Panggilan sistem terputus") bukan cara untuk menunjukkan kondisi kesalahan, tetapi peretasan yang memungkinkan programmer untuk menggabungkan pemblokiran read / wrote / etc dengan penanganan sinyal di loop utama. Seharusnya tidak pernah bocor ke pengguna.

Bug ini tidak muncul terlalu sering karena itu adalah suatu prestasi untuk mendapatkan kondisi yang tepat: yang write()harus dilakukan oleh builtin (bukan oleh perintah eksternal), ia harus mengisi penyangga pipa (pembaca di sisi lain ujungnya harus jauh lebih lambat atau tidak membaca dari pipa sama sekali tetapi masih hidup ), dan skrip harus menggunakan perangkap atau jendela terminal harus diubah ukurannya.

Dan karena artefak implementasi yang beragam, ini hanya mempengaruhi write()s yang terputus , bukan read()s atau open()s (seperti misalnya pemblokiran open()pipa bernama / fifo).

[1] formulir ini sudah dilaporkan beberapa waktu lalu.

mosvy
sumber