我想通过 SSH 连接到服务器,启动屏幕会话,cd
进入path/to/my/script/
,然后在test.sh
那里运行 。
作为初学者,我尝试了
ssh me@myserver.com screen -dm bash -c 'cd path/to/my/script/; pwd > ~/output.txt'
Run Code Online (Sandbox Code Playgroud)
并希望在 中看到,但我path/to/my/script/
在output.txt
那里看到了我的主目录。这意味着该cd
命令实际上不起作用,因此 bash 将无法运行test.sh
.
我该如何解决这个问题?
简短的回答:在命令周围添加一些额外的引号,如下所示:
ssh me@myserver.com "screen -dm bash -c 'cd path/to/my/script/; pwd > ~/output.txt'"
Run Code Online (Sandbox Code Playgroud)
要查看发生了什么,您可以指定-v
选项ssh
以获取一些调试信息。在这种情况下,对于原始命令,您将看到如下一行
debug1: Sending command: screen -dm bash -c cd path/to/my/script/; pwd > ~/output.txt
Run Code Online (Sandbox Code Playgroud)
而额外的引号将其更改为
debug1: Sending command: screen -dm bash -c 'cd path/to/my/script/; pwd > ~/output.txt'
Run Code Online (Sandbox Code Playgroud)
所以看起来 ssh 只是接受传递给它的参数,将它们全部连接起来,并让远程端再次将连接的参数列表拆分为单个参数。调用参数列表argv
(如在 C 中),您在原始版本中得到了如下内容:
argv[0] = ssh
argv[1] = me@myserver.com
argv[2] = screen
argv[3] = -dm
argv[4] = bash
argv[5] = -c
argv[6] = cd path/to/my/script/; pwd > ~/output.txt
Run Code Online (Sandbox Code Playgroud)
现在原则上,可以将to作为单独的参数ssh
传递argv[2]
给argv[6]
另一方,在这种情况下,它可能会按预期工作。但是正如调试行所示(并且它似乎也基于源代码),这些参数连接到字符串
screen -dm bash -c cd path/to/my/script/; pwd > ~/output.txt
Run Code Online (Sandbox Code Playgroud)
然后在远程端解释。由此也很清楚为什么它不做你想做的事情:现在你正在按顺序执行两件事,首先screen -dm bash -c cd path/to/my/script/
(因此screen
启动一个会话,其中只更改目录)从主目录执行,然后然后pwd > ~/output.txt
也从主目录执行。
为了完整起见,带双引号的命令的参数是
argv[0] = ssh
argv[1] = me@myserver.com
argv[2] = screen -dm bash -c 'cd path/to/my/script/; pwd > ~/output.txt'
Run Code Online (Sandbox Code Playgroud)
导致screen -dm bash -c 'cd path/to/my/script/; pwd > ~/output.txt'
发送到另一端(如调试行所示),它按预期工作。