Amb*_*jak 42 shell ssh cd-command
我试图通过 SSH 备份一些文件,但tar我得到了我的主文件夹,而不是我想要的那些。我做了一些进一步的测试,归结为:
ssh root@server /bin/sh -c "cd /boot && ls -l"
Run Code Online (Sandbox Code Playgroud)
令我惊讶的是,其中列出了/rootnot中的文件/boot。但是,如果我/bin/sh从终端运行整个命令,它就会正确地cd打印/boot文件。
这里发生了什么事?
小智 39
ssh 不允许您像您所做的那样将命令精确指定为要传递给远程主机上的 execvp 的一系列参数。相反,它将所有参数连接成一个字符串,并通过远程 shell 运行它们。在我看来,这是 ssh 中的一个主要设计缺陷......它在大多数方面都是一个表现良好的 unix 工具,但是当需要指定一个命令时,它选择使用单个整体字符串而不是 argv,例如它是为 MSDOS 或其他东西设计的!
由于 ssh 会将您的命令作为单个字符串传递给sh -c,因此您无需提供自己的sh -c. 当你这样做时,结果是
sh -c '/bin/sh -c cd /boot && ls -l'
Run Code Online (Sandbox Code Playgroud)
原始引用丢失。所以由 分隔的命令&&是:
`/bin/sh -c cd /boot`
`ls -l`
Run Code Online (Sandbox Code Playgroud)
第一个运行带有命令文本“cd”和$0=的 shell "boot"。“cd”命令成功完成,$0无关紧要,/bin/sh -c表示成功,然后ls -l发生。
Gil*_*il' 36
?这是一个引用问题。Ssh 已经运行了您在 shell 中传递给它的命令。当您传递多个参数时,它们之间用空格连接以构建一个字符串。所以你远程运行的远程命令是/bin/sh -c cd /boot && ls -l(没有引号,因为你的命令中的引号是由本地shell解释的)。
/bin/sh -c cd /boot运行/bin/sh并告诉它运行命令cd并设置$0为/boot. 完成此操作后,父 shell(由 启动的sshd)运行ls -l。
在您的情况下,只需删除sh -c完全无用的 除非您的远程外壳程序(如/etc/passwd或其他密码数据库所示)不理解此命令。
ssh root@server "cd /boot && ls -l"
Run Code Online (Sandbox Code Playgroud)
如果您需要调用不同的 shell,则必须引用远程命令以防止它被sshd. 例如,如果您的登录 shell 是 dash 并且您想运行 bash 命令:
ssh root@server 'bash -c "cd ~bob && ls -l"'
Run Code Online (Sandbox Code Playgroud)
slm*_*slm 10
我认为这更多地与 shell 如何解析选项有关。例如,这有效:
$ ssh root@server /bin/sh -c '"cd /boot && ls -l"'
Run Code Online (Sandbox Code Playgroud)
这与您的命令有相同的问题:
$ ssh root@server /bin/sh -c 'cd /boot && ls -l'
Run Code Online (Sandbox Code Playgroud)
如果您启用-v开关,ssh您可以看到发生了什么:
第一条命令:
debug1:发送命令:/bin/sh -c "cd /boot && ls -l"
第二条命令:
debug1:发送命令:/bin/sh -c cd /boot && ls -l
通常,当通过ssh您发送命令时,您必须特别注意引号并将引号括在引号中,因为各个层会将它们剥离。也不要打扰发送/bin/sh。
一旦您理解了以下引用,您就可以做非常有用的事情ssh。这将在远程服务器上运行该命令,但将结果收集在您运行该ssh命令的系统上的本地文件中:
$ ssh root@server 'free -m' > /tmp/memory.status
Run Code Online (Sandbox Code Playgroud)
或者这个,你在远程服务器上tar一个目录并在本地系统上创建它:
$ ssh remotehost 'tar zcvf - SOURCEDIR' | cat > DESTFILE.tar.gz
Run Code Online (Sandbox Code Playgroud)
通常,您不必指定要使用的 shell。这有效:
ssh user@host "cd /boot && pwd"
Run Code Online (Sandbox Code Playgroud)
但是,如果您的默认 shell 有问题,那么只需确保引用整个命令,包括 shell 调用。以下任一作品
ssh user@host '/bin/sh -c "cd /boot && pwd"'
ssh user@host "/bin/sh -c \"cd /boot && pwd\""
Run Code Online (Sandbox Code Playgroud)