Bagaimana bash memperlakukan ">> ()"

9

Saat bereksperimen dengan pengalihan output dan penggantian proses, saya menemukan perintah berikut dan hasil yang dihasilkan:

    me @ elem: ~ $ echo foo>> (cat); bilah gema
    batang
    saya @ elem: ~ $ foo

(Ya, baris baru yang kosong pada akhirnya memang disengaja.)

Jadi bash echo bar, cetak prompt saya yang biasa, echo foo, echo a newline, dan tinggalkan kursor saya di sana. Jika saya menekan enter lagi, itu akan mencetak prompt saya pada baris baru dan membiarkan kursor mengikutinya (seperti yang diharapkan ketika seseorang menekan enter pada baris perintah kosong).

Saya mengharapkannya untuk menulis foo ke deskriptor file, cat membacanya dan echo foo, bilah gema gema kedua, dan kemudian kembali ke command prompt. Tapi jelas bukan itu masalahnya.

Bisakah seseorang tolong jelaskan apa yang terjadi?

Stanley Yu
sumber
Saya ingin menyarankan mencari jawaban pada ini: unix.stackexchange.com/questions/182800/… Ini menjelaskan pengalihan ganda, dan akan menjelaskan mengapa Anda mengakhiri dengan hasil yang berbeda. Baik Muru, dan Michael Hormers.
No Time
Untuk pertanyaan yang secara eksplisit berkaitan dengan mengapa output dari substitusi proses muncul setelah prompt (dan dalam beberapa keadaan tidak muncul sama sekali) di beberapa versi shell Bourne Again, lihat unix.stackexchange.com/questions/471987 .
JdeBP

Jawaban:

9

Anda mungkin melihat fooditampilkan sebelum bar, setelah bar, atau bahkan setelah prompt, tergantung pada waktu. Tambahkan sedikit keterlambatan untuk mendapatkan waktu yang konsisten:

$ echo foo > >(sleep 1; cat); echo bar; sleep 2 
bar
foo
$

barmuncul segera, lalu foosetelah satu detik, lalu prompt berikutnya setelah detik lainnya.

Apa yang terjadi adalah bahwa bash menjalankan proses penggantian di latar belakang.

  1. Proses bash utama memulai subkulit untuk dieksekusi sleep 1; cat, dan mengatur pipa untuk itu.
  2. Proses bash utama dijalankan echo foo. Karena ini tidak mengisi buffer pipa, echoperintah berakhir tanpa pemblokiran.
  3. Proses bash utama dijalankan echo bar.
  4. Proses bash utama meluncurkan perintah sleep 2.
  5. Sementara itu, subshell meluncurkan perintah sleep 1.
  6. Setelah sekitar 1 detik, sleep 1kembali dalam proses. Subproses mulai dijalankan cat.
  7. cat menyalin inputnya ke outputnya (yang ditampilkan di layar) dan kembali.
  8. Subkulit telah menyelesaikan tugasnya, keluar.
  9. Setelah sedetik lagi, sleep 2kembali. Proses shell utama selesai dijalankan dan Anda bisa melihat prompt berikutnya.
Gilles 'SANGAT berhenti menjadi jahat'
sumber
3

Anda tidak perlu proses substitusi untuk mendapatkan efek itu. Coba ini:

( echo foo | cat & )

Anda akan mendapatkan hasil yang sama (tanpa bar; Saya akan meninggalkan itu sebagai latihan) dan untuk alasan yang sama. Dalam kedua kasus, catdimulai sebagai tugas latar belakang. Dalam baris saya di sini, itu eksplisit. Dalam kasus substitusi proses, ini juga eksplisit - ini adalah proses terpisah yang dilampirkan ke deskriptor file nama - tetapi mungkin tidak sejelas itu.

Proses anak tidak harus berakhir sebelum bashmencetak prompt berikutnya. Dan karena outputnya di-buffer, ia tidak mengeluarkan apa-apa sampai ia berakhir. Pada saat itu, bash baru saja dicetak $pada stderr, dan sekarang proses latar belakang keluar setelah pencetakan foodan baris baru.

rici
sumber