Ya, bash
seperti di ksh
( di mana fitur tersebut berasal), proses di dalam proses substitusi tidak menunggu (sebelum menjalankan perintah berikutnya dalam skrip).
untuk <(...)
satu, itu biasanya baik seperti di:
cmd1 <(cmd2)
shell akan menunggu cmd1
dan cmd1
biasanya akan menunggu cmd2
berdasarkan pembacaan sampai akhir file pada pipa yang diganti, dan bahwa end-file biasanya terjadi ketika cmd2
mati. Itulah alasan yang sama mengapa beberapa kerang (tidak bash
) tidak perlu menunggu untuk cmd2
masuk cmd2 | cmd1
.
Untuk cmd1 >(cmd2)
, bagaimanapun, bahwa umumnya tidak terjadi, karena lebih cmd2
yang biasanya menunggu cmd1
di sana sehingga umumnya akan keluar setelah.
Itu sudah diperbaiki zsh
yang menunggu di cmd2
sana (tetapi tidak jika Anda menuliskannya sebagai cmd1 > >(cmd2)
dan cmd1
bukan bawaan, gunakan {cmd1} > >(cmd2)
sebagai gantinya yang didokumentasikan ).
ksh
tidak menunggu secara default, tetapi memungkinkan Anda menunggu dengan wait
builtin (itu juga membuat pid tersedia $!
, meskipun itu tidak membantu jika Anda melakukannya cmd1 >(cmd2) >(cmd3)
)
rc
(dengan cmd1 >{cmd2}
sintaks), sama seperti ksh
kecuali Anda bisa mendapatkan semua proses latar belakang dengan $apids
.
es
(juga dengan cmd1 >{cmd2}
) menunggu cmd2
like in zsh
, dan juga menunggu redirections cmd2
dalam <{cmd2}
proses.
bash
memang membuat pid dari cmd2
(atau lebih tepatnya dari subkulit seperti itu berjalan cmd2
dalam proses anak dari subkulit itu meskipun itu adalah perintah terakhir di sana) tersedia di $!
, tetapi tidak membiarkan Anda menunggu untuk itu.
Jika Anda harus menggunakan bash
, Anda dapat mengatasi masalah dengan menggunakan perintah yang akan menunggu kedua perintah dengan:
{ { cmd1 >(cmd2); } 3>&1 >&4 4>&- | cat; } 4>&1
Itu membuat keduanya cmd1
dan cmd2
memiliki fd 3 terbuka untuk sebuah pipa. cat
akan menunggu akhir file di ujung yang lain, jadi biasanya hanya akan keluar ketika keduanya cmd1
dan cmd2
sudah mati. Dan shell akan menunggu cat
perintah itu. Anda dapat melihat bahwa sebagai jaring untuk menangkap penghentian semua proses latar belakang (Anda dapat menggunakannya untuk hal-hal lain yang dimulai di latar belakang seperti dengan &
, coprocs atau bahkan perintah yang melatarbelakangi diri mereka sendiri asalkan mereka tidak menutup semua deskriptor file mereka seperti yang biasanya dilakukan daemon ).
Perhatikan bahwa berkat proses subkulit sia-sia yang disebutkan di atas, ia bekerja bahkan jika cmd2
menutup fd 3-nya (perintah biasanya tidak melakukan itu, tetapi beberapa suka sudo
atau ssh
tidak). Versi masa depan pada bash
akhirnya dapat melakukan optimasi di sana seperti di shell lain. Maka Anda akan membutuhkan sesuatu seperti:
{ { cmd1 >(sudo cmd2; exit); } 3>&1 >&4 4>&- | cat; } 4>&1
Untuk memastikan masih ada proses shell tambahan dengan fd 3 yang terbuka menunggu sudo
perintah itu.
Catatan yang cat
tidak akan membaca apa pun (karena proses tidak menulis di fd 3 mereka). Itu hanya ada untuk sinkronisasi. Ini akan melakukan hanya satu read()
panggilan sistem yang akan kembali tanpa hasil di akhir.
Anda sebenarnya dapat menghindari berjalan cat
dengan menggunakan substitusi perintah untuk melakukan sinkronisasi pipa:
{ unused=$( { cmd1 >(cmd2); } 3>&1 >&4 4>&-); } 4>&1
Kali ini, itu shell bukan cat
yang membaca dari pipa yang ujungnya terbuka pada fd 3 dari cmd1
dan cmd2
. Kami menggunakan tugas variabel sehingga status keluar dari cmd1
tersedia di $?
.
Atau Anda bisa melakukan proses substitusi dengan tangan, dan kemudian Anda bahkan bisa menggunakan sistem Anda sh
karena itu akan menjadi sintaksis shell standar:
{ cmd1 /dev/fd/3 3>&1 >&4 4>&- | cmd2 4>&-; } 4>&1
meskipun perhatikan seperti disebutkan sebelumnya bahwa tidak semua sh
implementasi akan menunggu cmd1
setelah cmd2
selesai (meskipun itu lebih baik daripada sebaliknya). Waktu itu, $?
berisi status keluar dari cmd2
; meskipun bash
dan zsh
membuat cmd1
status keluar tersedia di ${PIPESTATUS[0]}
dan $pipestatus[1]
masing - masing (lihat juga pipefail
opsi dalam beberapa shell sehingga $?
dapat melaporkan kegagalan komponen pipa selain yang terakhir)
Catatan yang yash
memiliki masalah serupa dengan fitur pengalihan prosesnya .cmd1 >(cmd2)
akan ditulis di cmd1 /dev/fd/3 3>(cmd2)
sana. Tetapi cmd2
tidak menunggu dan Anda tidak dapat menggunakannya wait
untuk menunggu dan pidnya tidak tersedia dalam $!
variabel juga. Anda akan menggunakan pekerjaan yang sama untuk bash
.