0

I am trying to run an inline ssh command which looks like this:

ssh user@127.0.0.1 "df / -h | awk 'FNR == 2 {print $3}'"

I would expect the output to be 3.8G (as this is the second line, third column) but instead, I am getting /dev/sda1 6.9G 3.8G 2.8G 58% /(the entire second line).

This means that the FNR == 2 is working but the {print $3} is not.

If I run that command directly on the machine that I am ssh'ing into then I get the expected result, just not when calling it through an inline ssh command as above.

This code will eventually ran within a bash script. Is it not possible to use print in this way? If not, is there another method that you can suggest? I am relatively new to terminal life so please bear with me.

thomasters
  • 183
  • 1
  • 15
  • 2
    Does this answer your question? [Difference between single and double quotes in Bash](https://stackoverflow.com/questions/6697753/difference-between-single-and-double-quotes-in-bash) – oguz ismail Mar 17 '20 at 17:22
  • 1
    Yes, it does indirectly answer my question and it is also very useful to know. Thanks for the link. – thomasters Mar 17 '20 at 17:46

2 Answers2

2

The joys of shell quoting. The line:

ssh user@127.0.0.1 "df / -h | awk 'FNR == 2 {print $3}'"

Is parsed by the shell, which invokes ssh with two arguments:

user@127.0.01 and df / -h | awk 'FNR == 2 {print }' The $3 was interpolated, and (I'm assuming) was empty. To prevent that, you have many options. One of which is:

ssh user@127.0.0.1 << \EOF
df / -h | awk 'FNR == 2 {print $3}'
EOF

another is:

ssh user@127.0.0.1 sh -c '"df / -h | awk '"'"'FNR == 2 {print $3}'"'"'"'
William Pursell
  • 204,365
  • 48
  • 270
  • 300
2

The problem resides in the way you pass you ssh arguments.

By calling:

ssh user@127.0.0.1 "df / -h | awk 'FNR == 2 {print $3}'"

You are passing two arguments:

  • user@127.0.0.1
  • "df / -h | awk 'FNR == 2 {print $3}'"

Since your second argument is given inside double quotes, the $3 variable will be expanded. You can prevent this variable expansion by escaping the dollar sign:

ssh user@127.0.0.1 "df / -h | awk 'FNR == 2 {print \$3}'"
vdavid
  • 2,434
  • 1
  • 14
  • 15
  • nit: (a point which seems to cause a lot of confusion) The 2nd argument passed to `ssh` does *not* contain double quotes. `ssh` never sees them. – William Pursell Mar 17 '20 at 17:40
  • @WilliamPursell Yup, you’re right, that’s why I said that the argument is given *inside* double quotes. But I cannot remove them when listing arguments, otherwise it would mean that I am evaluating the arguments before passing them (à la `set -x`) and we would not even see the `$3` which would be awkward at this point of the answer. – vdavid Mar 17 '20 at 17:50