Warum funktioniert die Prozessersetzung <() nicht mit ssh -F?

11

Ich habe einige vagabundierende virtuelle Maschinen. Um mich anzumelden, gebe ich den vagrant sshBefehl aus. Ich möchte mich mit einem regulären sshBefehl bei ihnen anmelden . Das vagrant ssh-configgibt die passende Konfigurationsdatei aus

$ vagrant ssh-config
Host default
  HostName 127.0.0.1
  User vagrant
  Port 2201
  UserKnownHostsFile /dev/null
  StrictHostKeyChecking no
  PasswordAuthentication no
  IdentityFile /home/cbliard/.vagrant.d/insecure_private_key
  IdentitiesOnly yes
  LogLevel FATAL

Wenn Sie diese Konfiguration in einer Datei ausgeben und mit verwenden ssh -F, funktioniert alles einwandfrei :

$ vagrant ssh-config > /tmp/config
$ ssh -F /tmp/config default
=> logged successfully

Wenn Sie den Prozessersetzungsoperator verwenden <(cmd), um die Erstellung der temporären Konfigurationsdatei zu verhindern, schlägt Folgendes fehl:

$ ssh -F <(vagrant ssh-config) default
Can't open user config file /proc/self/fd/11: No such file or directory

Der gleiche Fehler tritt bei der Verwendung auf <(cat /tmp/config)

$ ssh -F <(cat /tmp/config) default
Can't open user config file /proc/self/fd/11: No such file or directory

Ich benutze zsh und beobachte das gleiche Verhalten mit bash. Was mache ich hier falsch?

cbliard
quelle
2
Anscheinend schließt ssh alle unerwarteten Dateideskriptoren.
Strg-Alt-Delor

Antworten:

10

Der Befehl:

ssh -F <(vagrant ssh-config) default

führt den vagrantBefehl in einem separaten Prozess aus, wobei sein Standardout mit einer Pipe verbunden ist. Das andere Ende der Pipe ist als Dateideskriptor n(in Ihrem Fall 11) mit einem neuen Prozess verbunden, der ausgeführt wirdssh und die Shell wird ausgeführt:

ssh -F /proc/self/fd/n default

Das funktioniert nur, wenn ssh die Dateideskriptoren beim Start nicht geschlossen werden.

Leider schon.

Bei Verwendung zshbesteht eine Alternative darin, die =(...)Form der Prozessersetzung zu verwenden, bei der anstelle eines Rohrs und/proc/self/fd eine temporäre Datei verwendet wird.

Oder Sie können einen Dateideskriptor verwenden, sshder nicht geschlossen wird. Wenn Sie beispielsweise nichts füttern ssh(wenn der Remote-Befehl nichts von stdin liest), können Sie fd0 verwenden, z.

vagrant ssh-config | ssh -F /dev/stdin -n default
Stéphane Chazelas
quelle
Wunderbar. Damit =(...)funktioniert es wie ein Zauber und die temporäre Datei wird automatisch entfernt, wenn die sshSitzung endet. Die Variante mit /dev/stdinverbindet sich erfolgreich, wird aber sofort beendet.
Cbliard
1
@cbliard, ja, wenn der Befehl, den Sie am anderen Ende ausführen, eine interaktive Shell ist, liest er aus seinem Standard (der jetzt verbrauchte Pipe zum Vagabund), sieht den Eof und beendet ihn. Deshalb habe ich gesagt, wenn Sie nichts fütternssh .
Stéphane Chazelas
Ok, ich habe nicht verstanden, was du damit gemeint hast, wenn du nichts fütterstssh . Es ist jetzt klar.
Cbliard
Ist das noch wahr? Ich verwende erfolgreich: ssh -F <(cat ~/.ssh/config ~/.ssh/hosts)um 2 Konfigurationsdateien zusammenzuführen, wenn SSH ausgeführt wird. Und auf ZSH kann ich das tun : ssh -F <(vagrant ssh-config) default.
CMCDragonkai