I'm working on a platform that uses a lot such commands:
ssh login@server.com 'curl http://some_server/script.sh | bash'
This is really clean and handy to execute scripts remotely, however, I don't see anyway to get the output/exit code of the script. Anyone can figure out something to make sure the script has been properly executed (from the host launching the ssh point of view).
Best Answer
As @Zoredache points out,
ssh
relays the status of the remote command as its own exit status, so error detection works transparently over SSH. However, two important points require special consideration in your example.First,
curl
tends to be very lenient, treating many abnormal conditions as success. For example,curl http://serverfault.com/some-non-existent-url-that-returns-404
actually has an exit status of 0. I find this behavior counterintuitive. To treat those conditions as errors, I like to use the-fsS
flags:--fail
flag suppresses the output when a failure occurs, so thatbash
won't get a chance to execute the web server's 404 error page as if it were code.--silent --show-error
flags, together, provide a reasonable amount of error reporting.--silent
suppresses all commentary fromcurl
.--show-error
re-enables error messages, which are sent to STDERR.Second, you have a pipe, which means that a failure could occur in either the first or the second command. From the section about Pipelines in bash(1):
Side note: The
bash
documentation is relevant not because you pipe tobash
, but because (I assume) it is your remote user's login shell, and would therefore be the program that interprets the remote command line and handles the execution of the pipeline. If the user has a different login shell, then refer to that shell's documentation.As a concrete example,
yields the output
demonstrating that the
bash
at the end of the pipeline will mask the error status returned byfalse
. It will return 0 as long as it successfully executeswhoami
.In contrast,
yields
so that the failure in the first half of the pipeline is reported.
Putting it all together, then, the solution should be
That way, you will get a non-zero exit status if any of the following returns non-zero:
ssh
curl
bash
at the end of the pipelineFurthermore, if
curl -fsS
detects an abnormal HTTP status code, then it will:bash
to be executed