[ I am going to use /dev/null to illustrate the problem. If that bothers you, just replace it with any other shell initialization file, such as /etc/profile. ]
I am trying to invoke source within a shell called by ssh.
The following works:
host$ source /dev/null
host$ sh -c 'source /dev/null'
But the following fails:
host$ ssh localhost sh -c 'source /dev/null'
/dev/null: line 0: source: filename argument required
source: usage: source filename [arguments]
But if I make source the second command in the shell, then it works:
host$ ssh localhost sh -c 'echo; source /dev/null'
host$ ssh localhost sh -c ':; source /dev/null'
host$
The question is why cannot I invoke source as the first command in a shell through ssh? And how to do it properly? (And for a bonus answer, why does it work when it is the second command?)
[ And the source command will not be the only command called; it is just a requirement before I invoke the other commands on the same ssh command. ]
Your quoting is incomplete.
sh -c 'source /dev/null' invokes a new shell and passes it two parameters, the first is the option (-c), the second is the command-string for -c to operate on.
ssh localhost sh -c 'source /dev/null' invokes ssh to start a shell on localhost. This new shell is passed a command containing 4 words - in effect, the single-quotes are removed by ssh. This shell duly starts a second shell and passes it 3 parameters. In this case -c only receives source as the command-string.
You need additional quoting to replace the ones stripped by ssh. For example:
ssh localhost "sh -c 'source /dev/null'"
The reason ssh localhost sh -c 'echo; source /dev/null' appears to work is that ssh has passed two commands to the shell it starts: sh -c echo (which then exits), followed by source /dev/null
It may be helpful to imagine replacing ssh localhost with echo and seeing which quotes disappear.
The POSIX shell synopsis says:
sh -c [-abCefhimnuvx] [-o option]... [+abCefhimnuvx] [+o option]... command_string [command_name [argument...]] -c Read commands from the command_string operand. Set the value of special parameter 0 (see Special Parameters) from the value of the command_name operand and the positional parameters ($1, $2, and so on) in sequence from the remaining argument operands. No commands shall be read from the standard input.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With