Di zsh, perbedaan antara kucing <(kucing) vs kucing | kucing vs kucing = (kucing)?

18

Saya mengharapkan cat <(cat)dan cat | catmelakukan hal yang sama: menyalin baris dari stdin ke stdout. Pemahaman saya adalah bahwa keduanya akan mengeksekusi catdalam subshell, mengarahkan catstdout subshell ke pipa bernama sementara, dan kemudian menjalankan yang lain catdi shell saat ini dengan stdin diarahkan ke pipa.

Sebagai gantinya, cat <(cat)izinkan saya mengetik di terminal saya, tetapi tidak ada jalur input yang disalin dan ^Dgagal memberi sinyal EOF; cat | catbekerja seperti yang diharapkan.

Sebagai percobaan lebih lanjut, saya memeriksa apakah cat =(cat)memiliki kesulitan yang sama cat <(cat), tetapi berfungsi seperti yang saya harapkan: semua stdin hingga dapat ^Ddisalin ke stdout dalam sekali jalan.

Adakah yang bisa membantu saya memahami apa yang dilakukan zsh di bawah tenda?

Alan O'Donnell
sumber

Jawaban:

23
  1. a | bmenghubungkan STDOUTdari adan STDINdari bhanya dengan menggunakan dup/dup2. Kedua perintah dieksekusi secara paralel.

  2. a =(b)mengganti argumen menjadi adengan nama file sementara. bakan dieksekusi sebelumnya akarena file sementara harus dibuat sebelum dapat diteruskan kea

  3. a <(b)mengganti argumen menjadi adengan pipa bernama. adan bjalankan secara paralel. Ini sekarang menjadi tempat yang sedikit rumit:

    bada di latar belakang dan tidak bisa membaca dari terminal. Anda dapat mengujinya sendiri dengan menggunakan strace -p $PIDuntuk melampirkan proses kucing kedua Anda untuk melihat prosesnya.

    aSementara itu mencoba membaca dari nama pipa tetapi tidak bisa membaca apa pun karena btidak bisa membaca.

    • Ini berarti Anda pada dasarnya memiliki jalan buntu di mana amencoba membaca btetapi btidak dapat membaca STDINdan tidak dapat menulisa

Informasi lebih lanjut tentang proses latar belakang dan terminal dari man bash :

Untuk memfasilitasi implementasi antarmuka pengguna ke kontrol pekerjaan, sistem operasi mempertahankan gagasan ID grup proses terminal saat ini . Anggota grup proses ini (proses yang ID grup prosesnya sama dengan ID grup proses terminal saat ini) menerima sinyal yang dihasilkan keyboard seperti SIGINT . Proses-proses ini dikatakan berada di latar depan . Latar Belakangproses adalah mereka yang ID grup prosesnya berbeda dari terminal; proses seperti itu kebal terhadap sinyal yang dihasilkan keyboard. Hanya proses latar depan diizinkan untuk membaca dari atau, jika pengguna menentukan dengan stty tostop, tulis ke terminal. Proses latar belakang yang berusaha membaca dari (menulis hingga ketika stty tostop berlaku) terminal dikirim sinyal SIGTTIN (SIGTTOU) oleh driver terminal kernel, yang, kecuali tertangkap, menunda proses.

Ulrich Dangel
sumber
Bagus, terima kasih - ini sangat jelas!
Alan O'Donnell
1
Catatan ketika tidak interaktif, zsh mengarahkan input standar dari perintah latar belakang (termasuk yang ada dalam <(cmd)) /dev/null, sehingga perilakunya berbeda ( zsh -c 'cat <(cat)'segera kembali dan tidak menghasilkan apa-apa).
Stéphane Chazelas