首页 > 解决方案 > ssh bash -c exit status does not propagate

问题描述

According to man ssh and this previous answer, ssh should propagate the exit status of whatever process it ran on the remote server. I seem to have found a mystifying exception!

$ ssh myserver exit 34 ; echo $?
34

Good...

$ ssh myserver 'exit 34' ; echo $?
34

Good...

$ ssh myserver bash -c 'exit 34' ; echo $?
0

What?!?

$ ssh myserver
ubuntu@myserver $ bash -c 'exit 34' ; echo $?
34

So the problem does not appear to be either ssh or bash -c in isolation, but their combination does not behave as I would expect.

I'm designing a script to be run on a remote machine that needs to take an argument list that's computed on the client side. For the sake of argument, let's say it fails if any of the arguments is not a file on the remote server:

ssh myserver bash -c '
    for arg ; do
        if [[ ! -f "$arg" ]] ; then
            exit 1
        fi
    done
' arg1 arg2 ...

How can I run something like this and effectively inspect its return status? The test above seems to suggest I cannot.

标签: bashssh

解决方案


问题是报价丢失了。ssh只是连接参数,它不会重新引用它们,所以您在服务器上实际执行的命令是:

bash -c exit 34

-c选项只接受一个参数,而不是所有剩余的参数,所以它只是在执行exit34被忽略。

如果你这样做,你会看到类似的效果:

ssh myserver bash -c 'echo foo'

它只会回显一个空行,而不是foo.

你可以通过给一个参数来修复它ssh

ssh myserver "bash -c 'exit 34'"

或加倍引号:

ssh myserver bash -c "'exit 34'"

推荐阅读