Was macht "<& -"?

20

Ich habe einen Ausschnitt von Bash in den Hintergrund eines aus der Ferne ausgeführten ssh-Befehls kopiert:

ssh user@remote <<CMD
some process <&- >log 2>error &
CMD

Was macht <&-das?
Ich vermute, es ist dasselbe wie< /dev/null

Mein nächstes Verständnis ist , dass die drei wichtigsten Datei - Deskriptoren ( stdin, stdout, stderr) müssen geschlossen werden , um zu verhindern:

  1. Der Hintergrund des Jobs und das Beenden des Drehbuchs - irgendwie widersprüchlich?
  2. Wenn das Terminal geschlossen wird, werden alle Prozesse, die stdin vom Terminal akzeptieren, geschlossen?
Eric Francis
quelle
Obligatorischer Querverweis: Siehe Was sind die Steuerungs- und Umleitungsoperatoren der Shell? - obwohl alles, was über diesen Operator gesagt wird, ist, dass er "zum Schließen oder Duplizieren von Dateideskriptoren verwendet werden kann" und Sie "den entsprechenden Abschnitt Ihres Shell-Handbuchs" lesen sollten.
G-Man sagt, dass Monica
Wenn ich mich richtig erinnere, ssh -nNT user@remote 'command'wird eine nicht interaktive SSH-Sitzung erstellt. Hänge es &an den Hintergrund an, bevor du es nohupan das anfügst , commandum es am Laufen zu halten, wenn deine Verbindung unterbrochen wird.
Mark K Cowan
1
@MarkKCowan man sshschlägt vor, dass -N die Ausführung eines Remotebefehls vollständig deaktiviert, und ein schneller Test unterstützt dies.
Tom Hunt
Ach ja, ich habe -nNTR für die Reverse-Port-Weiterleitung verwendet. Ignorieren Sie die -N und -R dann :)
Mark K Cowan

Antworten:

30

<&-ist nicht ganz dasselbe wie < /dev/null. <&-Schließt fd 0, während < /dev/nulles vom Gerät umgeleitet wird /dev/null, das niemals Daten liefert und beim Lesen immer EOF gibt. Der Unterschied besteht hauptsächlich darin, dass ein read(2)Aufruf von einer geschlossenen FD (der <&-Fall) mit EBADF einen Fehler verursacht, wohingegen ein Aufruf von einer nullumgeleiteten FD keine gelesenen Bytes zurückgibt (Dateiende-Bedingung). Wenn Ihr Programm nie von stdin liest, spielt die Unterscheidung keine Rolle.

Das Schließen der FDs ist empfehlenswert, wenn Sie einen Hintergrund erstellen, da ein Hintergrundprozess hängen bleibt, wenn er versucht, etwas von TTY zu lesen. Dieses Beispiel behandelt jedoch nicht alles, was es sollte. idealerweise gäbe es irgendwo einen nohupoder setsidAufruf, um den Hintergrundprozess vollständig zu trennen.

Tom Hunt
quelle
Also sollte ich nohupzusätzlich zum Schließen Dateideskriptoren verwenden?
Eric Francis
2
Die gründlichste Methode (die die Art und Weise imitiert, wie sich Programme dämonisieren) ist so etwas wie setsid some process <&- >path/to/log 2>path/to/error. Die schnellere Methode ist so etwas wie nohup some process &.
Tom Hunt
2
@EricFrancis: Verwenden nohupmacht hier keinen Sinn. nohupVerhindern, dass der Prozess ein HUPSignal empfängt , wenn sein Steuerterminal geschlossen ist. Aber Sie hatten in diesem Fall kein Terminal.
cuonglm
@TomHunt: Der Hintergrundprozess hing nicht, die SSH-Sitzung.
Donnerstag,
2
Es ist keine gute Idee, die FDS 0, 1 und 2 zu schließen. Sie möchten nicht, dass die nächste erstellte FD einen dieser Werte annimmt. Besser, sie nach / dev / null umzuleiten
Murray Jensen
7

Siehe man bash:

  [n]<&word

wird zum Duplizieren von Eingabedateideskriptoren verwendet. Wenn es wordauf eine oder mehrere Ziffern erweitert wird, wird der mit bezeichnete Dateideskriptor nals Kopie dieses Dateideskriptors erstellt. Wenn die Ziffern in word keinen zur Eingabe geöffneten Dateideskriptor angeben, tritt ein Umleitungsfehler auf. Wenn word als ausgewertet wird, -wird der Dateideskriptor ngeschlossen. Wenn nnicht angegeben, wird die Standardeingabe (Dateideskriptor 0) verwendet.

Choroba
quelle
Die korrekte Definition ist, dass nicht angegeben ist, was passiert, wenn ein [n]<&wordWort mehr als eine Ziffer enthält.
Schily
Was meinst du? Ist das man bashfalsch
Eric Francis
@EricFrancis, da es im Standard nicht spezifiziert ist, bashentscheidet sich dafür, es auf eine vernünftige Art und Weise zu implementieren (für eine geeignete Definition von "vernünftig"). Andere Muscheln können dies tun oder nicht.
Muru
@muru Die Frage ist markiert bash, nicht posix-shell.
Barmar
@ Bar ok. So...?
Muru
7

<&- Standardeingabe schließen.

Die von POSIX definierte allgemeine Form lautet:

[n]<&word

Der Zweck des Dateideskriptors nist eine Kopie des mit bezeichneten Dateideskriptors word. Standard in wird angenommen, wenn nes weggelassen wird. Wenn dies der Fall wordist -, wird der Dateideskriptor ngeschlossen.

Dies ist nicht dasselbe </dev/null, da </dev/nulldie Standardeingabe immer noch geöffnet und an einen anderen Ort umgeleitet wurde.

Sie müssen alle Dateideskriptoren von Prozessen schließen, die an den ssh-Socket angehängt wurden. Andernfalls kann die ssh-Sitzung nicht geschlossen werden.

Sie können den Befehl auf einem Remote-Computer ausführen, ohne ihn an die SSH-Sitzung anzuhängen. Verwenden Sie dazu screen oder tmux :

ssh user@remote 'screen -S test -d -m command'
cuonglm
quelle
Warum abstimmen?
Donnerstag,