1

I'm trying to run the script test.sh (which is on my local machine) on a remote server. test.sh takes an argument that often has multiple words.

test.sh:

#!/bin/bash
while getopts b: opt;
do
  case $opt in
    b)
       bval="$OPTARG"
       ;;
  esac
done
echo $bval

It works fine on my local machine:

./test.sh -b "multi word arg"

Output:

multi word arg

But when I run it on a remote server, like so:

ssh -A user@remotehost "bash -s" -- < ./test.sh -b "multi word arg"

I get only:

multi

Any ideas on how I could pass the full, multi-word argument to the script?

  • Related, if not a dupe: https://unix.stackexchange.com/questions/450020/executing-sh-c-script-through-ssh-passing-arguments-safely-and-sanely – Kusalananda Mar 13 '20 at 23:10
  • Also https://unix.stackexchange.com/questions/205567/how-to-execute-an-arbitrary-simple-command-over-ssh-without-knowing-the-login-sh – Kusalananda Mar 13 '20 at 23:11

1 Answers1

2

You need another level of quotes: '"multi word arg"'

The first level of quotes is removed by your local shell, and ssh gets multi word arg. Then ssh, on the remote system, runs something like $SHELL -c "bash -s -- -b multi word arg" (where $SHELL is your login shell, most probably bash, again).The login shell then does quote removal (none to be removed) and word splitting, which is why you get one word.

To illustrate:

% ssh 192.168.0.2 'printf :%s:\\n' '"foo bar baz"'
:foo bar baz:
% ssh 192.168.0.2 'printf :%s:\\n' 'foo bar baz'
:foo:
:bar:
:baz:
muru
  • 72,889
  • This looks promising, but I'm hoping to run a full script that is stored locally on a remote server, which (AFAIK) requires the "bash -s" -- < ./test.sh -b "multi word arg" syntax. Using that syntax, when I wrapped "multi word arg" in an extra set of quotes, like so: '"multi word arg"', the output was an empty string - the -b flag didn't even get triggered. Is there an alternative to my syntax that would allow me to use the extra quote wrapping? – Jacob Stern Mar 12 '20 at 14:31
  • @JacobStern I get multi word arg as the output. Something else might messing with your command there. O.o Maybe try bash -xs to get debug output and update your question with that. – muru Mar 16 '20 at 05:36
  • You're right, this totally works! I realized I dropped the '--' when I ran the command, which was what caused it to fail. Your answer works perfectly. – Jacob Stern Mar 16 '20 at 15:47
  • One follow-up question - is there any way to do this if "multi word arg" is stored in a variable, like PHRASE="multi word arg"? (My full use case is to run this command within a shell script). When I try wrapping a variable in single quotes, ('$PHRASE' it treats the variable as a string literal rather than as a variable, and when I wrap the variable in double quotes ("$PHRASE"), it ignores the quotes and I get "multi" as output. Is this worth a new question? – Jacob Stern Mar 16 '20 at 16:02
  • @JacobStern you can swap the quotes around, perhaps: "'$PHRASE'", or use parameter expansion with quoting: "${PHRASE@Q}" – muru Mar 17 '20 at 02:17
  • Those both work! Thank you again. I'm going to ask a new question because the full use case requires multiple ssh tunnels, and that breaks this again, but that goes beyond the original question. Here is the new question – Jacob Stern Mar 17 '20 at 05:40