Hintergrundprozess Pipe-Input

14

wenn ich "aaa" auf dem Bildschirm anzeigen möchte:

(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

schlussfolgerung aus (3) und (4) -> losgelöster prozess haben noch ausgang geschaltet, der gesteuert, verwendet, umgeleitet werden kann ... aber nicht eingang!

Meine frage ist: versteht jemand warum und wie line (5) funktioniert ???

... "<& 0" ist die Abkürzung für "0 <& 0", warum das Umleiten von 0 auf 0 eine Lösung ist und was bei der Eingabe eines getrennten Prozesses wirklich passiert. Subshells sind nicht das Problem, die Verwendung von geschweiften Klammern {...} anstelle von (...) liefern dieselben Ergebnisse.

... und Frage 2: Gibt es eine bessere Lösung für "Eingaben für den getrennten Prozess" als Zeile (6)?

Asain Kujovic
quelle

Antworten:

12

Ja, gemäß POSIX werden Befehle, die im Hintergrund gestartet &wurden, von der Standardeingabe umgeleitet /dev/null.

Und in der Tat

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

ist der naheliegendste Weg, dies zu umgehen.

Es ist jedoch nicht klar, warum Sie einen Teil der Pipeline im Hintergrund ausführen möchten.

Stéphane Chazelas
quelle
Der Grund war, die PID eines bestimmten Befehls in der Pipe-Kette (cmd1 | {cmd2 &; pid2 = $ !;} | cmd3 ...) abzurufen. Daher ist / dev / null == & 0 Standard für BG-Prozesse. Wissen Sie auch, warum? "0 <& 0" funktioniert in bash ... und ist es sicher?
Asain Kujovic
3
@OmerMerdan POSIX sagt In allen Fällen wird diese Aktivität durch die explizite Umleitung der Standardeingabe außer Kraft gesetzt , was in gewisser Weise dem oben Gesagten widerspricht. Ich glaube bash, dass dies (und das klingt nach einer vernünftigen Interpretation) als Abbrechen der /dev/nullUmleitung interpretiert wird . Nun tun nicht viele Muscheln dasselbe. Ash und Pdksh nicht.
Stéphane Chazelas
Warum wird das 3<&-Teil benötigt und kann es sicher verwendet werden (wird das Rohr nicht geschlossen, bevor die vollständige Eingabe erfolgt)?
mvorisek
1
@Mvorisek, dieses fd 3 wird nur vorübergehend verwendet, um das ursprüngliche stdin wiederherzustellen. Wir schließen es, weil cmdes nicht benötigt wird. Wir schließen es, nachdem wir es auf fd 0 ( <&3kurz für 0<&3) gedoppelt haben .
Stéphane Chazelas
1
@Mvorisek, nohupleitet auch stdin / dev / null, so müssen Sie: { nohup sh -c 'cmd <&3 3<&-' & } 3<&0. Oder(trap '' HUP; cmd <&3 3<&- > nohup.out 2>&1 &) 3<&0
Stéphane Chazelas