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
  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. Commented Nov 20, 2013 at 11:50

2 Answers 2


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
  • 1
    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
    Commented Nov 20, 2013 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. Commented Nov 20, 2013 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
    Commented Nov 20, 2013 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. Commented Sep 4, 2016 at 13:38

based on @cbliard

This works:

ssh -F =(vagrant ssh-config ) -i =(generate ssh-identity)
  • Thanks! Can you clarify what =( ) does? I'm not familiar with it.
    – cbliard
    Commented Mar 24, 2020 at 8:04

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .