I have a bunch of Linux machines behind 2 gateways. To connect to set one I do

ssh -o ProxyCommand="ssh gateway1 nc %h %p" machines_behind_1
ssh -o ProxyCommand="ssh gateway2 nc --proxy %h %p --proxy-type socks4" machines_behind_2

To simplify this process, I thought I would create a environment variable to hold the proxycommand and simply use that. So I did

export PGWA='-o ProxyCommand="ssh gateway1 nc %h %p"'
export PGWB='-o ProxyCommand="ssh gateway2 nc --proxy %h %p --proxy-type socks4"'

Then, depending on the machine I want to connect, I would do

ssh $PGWA machine_behind_1
ssh $PGWB machine_behind_2 

But I get this error -

/bin/bash: -c: line 0: unexpected EOF while looking for matching `"'
/bin/bash: -c: line 1: syntax error: unexpected end of file

Any idea why?

I can't use any ssh_config tricks, because I don't know the hostnames ahead of time. I might create a new VM behind gateway1 , and I will need to use the first proxy command.

The only thing I can think of is create a new alias, a function or a shell script which basically does ssh -o foo $@ and use that instead. But then, I need to remember to create an alias/shell script or function for scp as well, which too I use regularly. I would rather be able to do it automatically.

I kinda hoped I could do something like ssh gw1-host and do some manipulation inside the config file to convert it to ssh -o foo host through the first gateway, but that kind of regex manipulation is not allowed inside the ssh_config.

Any way I can achieve what I want without individual ssh / scp alias/script/function?

EDIT: I had made a mistake with the quoting when I copy-pasted the environment variable into stack exchange here.

  • 2
    Did you really mean to have unbalanced quotes in your examples? Is that your problem? – Scott Nelson May 8 '16 at 21:57
  • Wow that was pretty stupid of me. I do have single quotes at the beginning and end, and double quotes within the ProxyCommand="" variable. – Hari Sundararajan May 8 '16 at 22:48
  • When in doubt, "quote everything" – cat May 9 '16 at 2:22

When you write $PGWA without quotes, this splits the value of PGWA at whitespace¹. Quote characters have no special meaning there, so you end up with the words -o, ProxyCommand="ssh, gateway1, nc, %h and %p".

See Why does my shell script choke on whitespace or other special characters? for more explanations.

A variable expansion outside of double quotes is almost always a mistake. It's always a mistake unless you know why you need to leave the double quotes off.

What you need to do is to pass two arguments to the SSH command: -o and ProxyCommand=ssh gateway2 nc --proxy %h %p --proxy-type socks4.

In zsh, you could just set PGWA to an array:

PGWA=(-o 'ProxyCommand=ssh gateway2 nc --proxy %h %p --proxy-type socks4')
ssh $PGWA …

In other shells such as bash and ksh, this requires more typing, because of their design misfeature that unquoted variable expansions undergo splitting and because of their explicit syntax for arrays:

PGWA=(-o 'ProxyCommand=ssh gateway2 nc --proxy %h %p --proxy-type socks4')
ssh "${PGWA[@]}" …

A method that would work in any sh-like shell and wouldn't require much typing would be to define functions.

pgwa () {
  typeset c="$1"; shift
  "$c" -o 'ProxyCommand=ssh gateway2 nc --proxy %h %p --proxy-type socks4' "$@"
pgwa ssh …

But I think the best solution would be to put all of these definitions in your .ssh/config where they belong. This way you wouldn't need any shell tricks and the configurations would work in other programs (rsync, sshfs, GUI file transfer programs, etc.). If you add a new VM behind gateway1, either add an entry to .ssh/config or use ssh -o HostName=new-vm something-behind-gateway1 …

¹ Plus other things that don't matter here.

  • Wow thank you. That was a pretty awesome explanation and links. The array technique works, but I think I will stick to functions .. – Hari Sundararajan May 8 '16 at 23:02
  • @HariSundararajan any reason for not using the .ssh/config file ? – Ciprian Tomoiagă May 10 '16 at 3:09

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.