我在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
...
答案 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/repo
和git 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