background proses pipa-input

14

jika saya ingin menampilkan "aaa" di layar:

(1)$: echo aaa | cat                 ... works OK
(2)$: echo aaa | ( cat )             ... works OK
(3)$: echo aaa | ( cat & )           ... NOT working
(4)$: ( echo aaa & ) | cat           ... works OK 
(5)$: echo aaa | ( cat <&0 & )       ... works ok in BASH (but not in SH)
(6)$: echo aaa | ( cat <&3 & ) 3<&0  ... works ok in BASH and SH

kesimpulan dari (3) dan (4) -> proses terlepas masih memiliki output yang terhubung yang dapat dikontrol, digunakan, diarahkan ..., tetapi tidak input!

Pertanyaan saya adalah: apakah seseorang mengerti mengapa dan bagaimana jalur (5) berfungsi ???

... "<& 0" adalah kependekan dari "0 <& 0", mengapa pengalihan 0 ke 0 adalah solusi, dan apa yang sebenarnya terjadi di belakang dengan input proses terpisah. Subshell bukan masalah, menggunakan kawat gigi {...} alih-alih (...) memberikan hasil yang sama.

... dan pertanyaan2: apakah ada solusi yang lebih baik untuk "memberikan input ke proses terpisah" daripada baris (6).

Asain Kujovic
sumber

Jawaban:

12

Ya, seperti yang disyaratkan oleh POSIX , perintah dimulai di latar belakang dengan &input standarnya dialihkan /dev/null.

Dan memang

{ cmd <&3 3<&- & } 3<&0

adalah cara paling jelas untuk mengatasinya.

Tidak jelas mengapa Anda ingin menjalankan bagian dari pipa di latar belakang.

Stéphane Chazelas
sumber
alasannya adalah untuk mendapatkan PID dari satu perintah tertentu di dalam rantai pipa (cmd1 | {cmd2 &; pid2 = $ !;} | cmd3 ..., jadi / dev / null == & 0 adalah standar untuk proses BG, apakah Anda juga tahu mengapa "0 <& 0" berfungsi di bash ... dan apakah itu aman?
Asain Kujovic
3
@OmerMerdan POSIX mengatakan Dalam semua kasus, pengalihan standar input standar akan mengesampingkan aktivitas ini , yang bertentangan dengan apa yang dikatakan di atas, jadi saya percaya bashmenafsirkannya (dan itu terdengar seperti interpretasi yang masuk akal) sebagai membatalkan /dev/nullpengalihan. Sekarang, tidak banyak cangkang yang melakukan hal yang sama. Abu dan pdksh tidak.
Stéphane Chazelas
Mengapa 3<&-bagian itu diperlukan dan apakah aman untuk menggunakannya (tidak akan menutup pipa sebelum input penuh dibaca)?
mvorisek
1
@Vorisek, fd 3 itu hanya digunakan sementara untuk mengembalikan stdin yang asli. Kami menutupnya karena cmdtidak membutuhkannya. Kami menutupnya setelah kami menimpanya ke fd 0 ( <&3kependekan dari 0<&3).
Stéphane Chazelas
1
@Mvorisek, nohupjuga pengalihan stdin ke / dev / null, sehingga Anda akan perlu: { nohup sh -c 'cmd <&3 3<&-' & } 3<&0. Atau(trap '' HUP; cmd <&3 3<&- > nohup.out 2>&1 &) 3<&0
Stéphane Chazelas