¿Por qué la sustitución de proceso <() no funciona con ssh -F

11

Tengo algunas máquinas virtuales vagabundas. Para iniciar sesión, emito el vagrant sshcomando. Quiero iniciar sesión en ellos usando el sshcomando regular . Las vagrant ssh-configsalidas del archivo de configuración adecuado

$ 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

Al generar esta configuración en un archivo y usar con ssh -F, todo funciona bien:

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

Cuando se utiliza el operador de sustitución de procesos <(cmd)para evitar la creación del archivo de configuración temporal, falla:

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

El mismo error ocurre cuando se usa <(cat /tmp/config)

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

Estoy usando zsh y observo el mismo comportamiento con bash. ¿Qué estoy haciendo mal aquí?

cbliard
fuente
2
Parece que ssh está cerrando todos los descriptores de archivos inesperados.
ctrl-alt-delor

Respuestas:

10

El comando:

ssh -F <(vagrant ssh-config) default

ejecuta el vagrantcomando en un proceso separado con su stdout conectado a una tubería. El otro extremo de la tubería está conectado como descriptor de archivo n(en su caso, es 11) a un nuevo proceso que se ejecuta sshy se ejecuta el shell:

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

Ahora, eso solo funciona si sshno cierra sus descriptores de archivo al inicio.

Lamentablemente lo hace.

Si se usa zsh, una alternativa es usar la =(...)forma de sustitución de proceso donde, en lugar de usar una tubería /proc/self/fd, utiliza un archivo temporal.

O podría usar un descriptor de archivo que sshno se cierre. Por ejemplo, si no está alimentando nada ssh(si el comando remoto no está leyendo nada de stdin), puede usar fd0, por ejemplo:

vagrant ssh-config | ssh -F /dev/stdin -n default
Stéphane Chazelas
fuente
1
Maravilloso. Con =(...)esto funciona de maravilla y el archivo temporal se elimina automáticamente cuando sshfinaliza la sesión. La variante con se /dev/stdinconecta con éxito pero sale inmediatamente.
Cbliard
1
@cbliard, sí, si el comando que ejecutas en el otro extremo es un shell interactivo, leerá desde su stdin (que es la tubería ahora usada para vagabundear) ver el eof y salir. Por eso estaba diciendo que si no le estás dando de comerssh .
Stéphane Chazelas
Ok, no entendí a qué te referías con si no estás alimentando nadassh . Ahora está claro.
Cbliard
¿Sigue siendo cierto? Estoy usando con éxito: ssh -F <(cat ~/.ssh/config ~/.ssh/hosts)para unir 2 archivos de configuración al ejecutar SSH. Y en ZSH, puedo hacer esto: ssh -F <(vagrant ssh-config) default.
CMCDragonkai
1

basado en @cbliard

Esto funciona:

ssh -F =(vagrant ssh-config ) -i =(generate ssh-identity)
Sebastian Wagner
fuente
¡Gracias! ¿Puedes aclarar qué =( )hace? No estoy familiarizado con eso.
Cbliard