I'm pretty sure that's because of the way SSH passes a command line to the remote end and it does that by concatenating all the arguments it gets, joining them with spaces and letting the shell on the remote parse and execute that.
Consider e.g. that ssh somehost ls -l /etc/passwd
works the same as ssh somehost 'ls -l /etc/passwd'
, the latter doesn't give an error about a weirdly named command not existing, unlike it does if you just run 'ls -l /etc/passwd'
directly on a shell command line.
So,
ssh somehost bash -c 'test whatever || echo no'
turns into the command line
bash -c test whatever || echo no
where Bash gets to run the command test
, with $0
set to whatever
. test
with no args fails, so the || echo
runs. You can try something like ssh somehost bash -c 'ls -l /etc/passwd'
too, it should just run ls
in your remote home directory.
So, try without the intermediate shell:
ssh server02 'test -f /etc/passwd && echo passwd exists || echo "$(hostname): passwd does not exist"'
or you could do something like
ssh server02 'bash -c "test -f /etc/passwd && echo yes || echo \"\$(hostname): no\"'
but the quoting there does get icky if you want to nest another quoted string and make sure it's the innermost shell that runs any expansions you have. It doesn't matter that much with $(hostname)
since it'll give the same result from either shell on the remote, but in a more general case the quoting hell is there. In complex cases like that, it'd be far easier to just create a file on the remote and run the script from there.
This is basically the same issue as in ssh command with quotes.
See also Executing `sh -c` script through SSH (passing arguments safely and sanely) for other solutions for passing complex commands, and How to execute an arbitrary simple command over ssh without knowing the login shell of the remote user? for the rarer case involving a possibly unknown remote login shell.
ssh somehost 'test -f ... && echo yes || echo no'
directly, without an intervening shell. That is unless you need it because you want to run the script on a different shell than the login shell of the remote user. Then you need an additional set of quotes. – ilkkachu Jun 14 '22 at 06:46-f
becomes an argument tobash
, not totest
. If your local shell is Bash then you may find this helpful: How can I single-quote or escape the whole command line in Bash conveniently? – Kamil Maciorowski Jun 14 '22 at 06:51