Menurut dokumentasinya, bash menunggu hingga semua perintah dalam pipa selesai berjalan sebelum melanjutkan
Shell menunggu semua perintah dalam pipa untuk berakhir sebelum mengembalikan nilai.
Jadi mengapa perintah yes | true
selesai segera? Bukankah seharusnya yes
loop selamanya dan menyebabkan pipa tidak pernah kembali?
Dan sebuah subquestion: menurut spec POSIX , shell pipelines dapat memilih untuk kembali setelah perintah terakhir selesai atau menunggu sampai semua perintah selesai. Apakah kerang biasa memiliki perilaku yang berbeda dalam pengertian ini? Apakah ada cangkang di mana yes | true
akan berulang selamanya?
yes | tee >(true) >/dev/null
akan melakukan apa yang Anda harapkan, btw, seperti yangtee
berlanjut sampai semua penulis mati, sehinggatrue
keluar tidak akan mengganggu sepenuhnya.true
pada dasarnya adalah sebuah{return 0;}
program, jadi saya tidak akan berharap itu berjalan lama, apalagi selamanya.Jawaban:
Saat
true
keluar, sisi baca pipa ditutup, tetapiyes
terus mencoba menulis ke sisi tulis. Kondisi ini disebut "pipa rusak", dan menyebabkan kernel mengirimSIGPIPE
sinyalyes
. Karenayes
tidak melakukan sesuatu yang istimewa pada sinyal ini, itu akan dibunuh. Jika mengabaikan sinyal,write
panggilannya akan gagal dengan kode kesalahanEPIPE
. Program yang melakukan itu harus dipersiapkan untuk memperhatikanEPIPE
dan berhenti menulis, atau mereka akan masuk ke loop yang tak terbatas.Jika Anda melakukan
strace yes | true
1, Anda dapat melihat kernel mempersiapkan kedua kemungkinan:strace
sedang menonton acara melalui API debugger, yang pertama kali memberitahukannya tentang panggilan sistem yang kembali dengan kesalahan, dan kemudian tentang sinyal. Namun dariyes
perspektif, sinyal terjadi terlebih dahulu. (Secara teknis, sinyal dikirim setelah kernel mengembalikan kontrol ke ruang pengguna, tetapi sebelum instruksi mesin dijalankan lagi, sehingga fungsiwrite
"pembungkus" di perpustakaan C tidak mendapatkan kesempatan untuk mengaturerrno
dan kembali ke aplikasi.)1 Sedihnya,
strace
khusus untuk Linux. Sebagian besar Unix modern memiliki beberapa perintah yang melakukan hal serupa, tetapi sering memiliki nama yang berbeda, mungkin tidak memecahkan kode syscall argumen secara menyeluruh, dan kadang-kadang hanya berfungsi untuk root.sumber
yes
ada yang terhubung ke pipa.yes
dari mendapatkan SIGPIPE, karena FD yang ditulisnya tidak terhubung ke pipa.yes >/dev/null
berulang selamanya. Ini sama sekali tidak menunjukkan tentang pipa yang tidak juga berlaku untuk perintah sederhana (seperti perilaku menunggu untuk penghentian yang Tom tunjukkan juga berlaku untuk perintah sederhana).write()
(fungsi dalam libc) tidak kembali (kontrol transfer ke PC yang mengikutinya) sampai setelah pengendali sinyal telah berjalan, tetapi karena pengendali sinyal mengakhiri program, kontrol tidak pernah ditransfer dan karenanyawrite()
tidak pernah kembali. Ya, itu diimplementasikan di kernel denganxxx_write()
mengembalikan beberapa fungsi-EPIPE
, tetapi kami sedang men-debug program ruang pengguna dan tidak tertarik dengan itu.Tidak mungkin, karena
yes
perintahnya menggunakan pipa, dan itu akan gagal ketika pipa rusak.sleep
di sisi lain, tidak menggunakan pipa, jadi:akan berjalan setidaknya selama 10.0000000 detik.
sumber
true
builtin. Hal ini berlaku untuk versi terbaru dariBourne Shell
,ksh93
,zsh
. Jika Anda menekan^Z
ketika perintah seperti itu berjalan, ini akan menunda tidur dan shell tidak akan pernah bisa pulih tanpa bantuan eksternal.sbrk()
. Versi portabel dan terawat ada dalam bundel alat schily dan @Charles Duffy telah menemukan lokasi untuk informasi ;-)bsh
(Berthold Shell dari VBERTOS, versi memori virtual yang disempurnakan UNOS - klon UNIX pertama). Bsh memang mendapatkan banyak fitur csh pada tahun 1984 dan 1985 tetapi mekanisme alias dari UNOS lebih unggul daripada yang dari csh pada tahun 1980. Fitur Bourne Shell baru lainnya adalah dari POSIX, untuk memungkinkannya mendekati kepatuhan POSIX.