11

I have some vagrant virtual machines. To log into them I issue the vagrant ssh command. I want to log into them using regular ssh command. The vagrant ssh-config outputs the suitable config file

$ 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

When outputing this config in a file and using with ssh -F, everything works fine:

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

When using process substitution operator <(cmd) to prevent the creation of the temporary config file, it fails:

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

Same error happens when using <(cat /tmp/config)

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

I am using zsh and I observe the same behavior with bash. What am I doing wrong here?

  • 2
    Looks like ssh is closing all unexpected file descriptors. – ctrl-alt-delor Nov 20 '13 at 11:50
10

The command:

ssh -F <(vagrant ssh-config) default

runs the vagrant command in a separate process with its stdout connected to a pipe. The other end of the pipe is connected as file descriptor n (in your case it's 11) to a new process that runs ssh and the shell runs:

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

Now, that only works if ssh doesn't close its file descriptors on startup.

Unfortunately, it does.

If using zsh, an alternative is to use the =(...) form of process substitution where instead of using a pipe and /proc/self/fd, it uses a temp file.

Or you could use a file descriptor that ssh doesn't close. For instance, if you're not feeding anything to ssh (if the remote command is not reading anything from stdin) you could use fd 0, e.g.:

vagrant ssh-config | ssh -F /dev/stdin -n default
  • Wonderful. With =(...) it works like a charm and the temporary file is automatically removed when the ssh session ends. The variant with /dev/stdin connects successfully but exits immediately. – cbliard Nov 20 '13 at 13:28
  • 1
    @cbliard, yes, if the command you run on the other end is an interactive shell, it will read from its stdin (which is the now used up pipe to vagrant) see the eof and exit. That's why I was saying if you're not feeding anything to ssh. – Stéphane Chazelas Nov 20 '13 at 15:11
  • Ok, I did not understand what you meant with if you're not feeding anything to ssh. It is now clear. – cbliard Nov 20 '13 at 15:47
  • Is this still true? I am successfully using: ssh -F <(cat ~/.ssh/config ~/.ssh/hosts) to join 2 config files together when running SSH. And on ZSH, I can do this: ssh -F <(vagrant ssh-config) default. – CMCDragonkai Sep 4 '16 at 13:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.