SSH¶
Command quoting¶
Tip
Read POSIX (unix) basics first.
SSH only takes a simple string as command to send to the remote end 1.
A normal SSH-client joins the passed command and all arguments with a space as separator, and sends this as command string (with an "exec" request; if no command is passed it uses "shell" instead).
This means the following commands are equivalent:
ssh server printf '~%s~' value1 value2
ssh server printf '~%s~' "value1 value2"
ssh server 'printf ~%s~ value1 value2'
ssh server printf ~%s~ value1 value2
The ssh-server retrieves the shell for the user, e.g. /bin/bash, and runs execv("/bin/bash", ["-bash", "-c", command]), i.e. forwards the command string as one argument to $SHELL -c. (The leading - in argv[0] marks a login shell.)
This means the shell on the server splits arguments again and repeats expansions.
To actually get quoting through you need to use nested quotes:
The %q format from printf can be used to automate quoting; a command can be fully quoted by wrapping it in "$(printf ' %q' ...)", like:
As an alternative you can use the @Q parameter transformation; store the command to run in an array and then expand with quoted transformation:
See sshsystem for a wrapper script that handles normal options to ssh and escapes the command.
If you actually need expansions on the server (like ~serveruser) you’re on your own…