ssh server bash -c" cd / tmp&& git pull" ,cd不起作用,需要先添加echo

时间:2017-04-26 21:50:53

标签: bash ssh

我在ubuntu 15.04上,我的ssh客户端版本是

OpenSSH_6.9p1 Ubuntu-2ubuntu0.2, OpenSSL 1.0.2d 9 Jul 2015

当我尝试运行以下命令ssh admin@server bash -c 'cd /path/to/repo && git pull'时,cd无效,我得到了

fatal: Not a git repository (or any of the parent directories): .git

但是,如果我这样做

ssh admin@server bash -c 'echo test && cd /path/to/repo && git pull'

然后它起作用

Already up-to-date.

当然,我很清楚echo不应该改变任何东西,但经过几次尝试,几天后在几个不同的服务器上(尽管都在debian上)我现在肯定有这个错误。 在其他服务器上,我尝试了命令cd /tmp && pwd,然后我得到了我的主目录,如果我echo toto && /tmp && pwd我打印/tmp ...

2 个答案:

答案 0 :(得分:3)

不幸的是,ssh通过一个命令行字符串传递给远程上的$SHELL -c。你的报价没有效果。

运行时

ssh admin@server bash -c 'cd /path/to/repo && git pull'

这是在远程服务器上运行的(使用$SHELL -c):

bash -c cd /path/to/repo && git pull

因此,Bash被赋予单个命令(cd)和未使用的参数,然后单独地,您还在主目录中运行git pull

另一方面,当你运行

ssh admin@server bash -c 'echo test && cd /path/to/repo && git pull'

这是在远程服务器上运行的:

bash -c echo test && cd /path/to/repo && git pull

第一部分再次无用,但运行整个命令的shell会执行cd /path/to/repogit pull。哪个有用。

您可能想要做的是

ssh admin@server 'cd /path/to/repo && git pull'

答案 1 :(得分:2)

existing answer by ephemient在原因方面完全正确。

要添加备用解决方案 - 当您的远程代码包含sh -c将错误解释的构造时,该解决方案可用 - 请考虑:

repo=/path/to/repo                 ## here, this works even when your path contains
                                   ## nonprintable or otherwise surprising characters
printf -v repo_q '%q' "$repo"      ## ...because we're asking your local copy of bash
                                   ## to generate a quoted/escaped copy of the value
                                   ## that will 'eval' back to its original meaning
                                   ## when interpreted by bash

## to ensure that it's interpreted by bash, we pass 'bash -s' as the command to ssh
## with an *unquoted* heredoc (<<EOF, vs <<'EOF'), with the escaped value expanded
ssh admin@server 'bash -s' <<EOF
cd $repo_q && git pull
EOF