我有一个脚本,用于ssh
登录远程机器、cd
特定目录,然后启动守护程序。原始脚本如下所示:
ssh server "cd /tmp/path ; nohup java server 0</dev/null 1>server_stdout 2>server_stderr &"
Run Code Online (Sandbox Code Playgroud)
此脚本似乎工作正常。但是,对于用户输入错误路径导致cd
失败的情况并不稳健。由于 ,即使失败;
,此命令也会尝试运行该nohup
命令cd
。
明显的修复不起作用:
ssh server "cd /tmp/path && nohup java server 0</dev/null 1>server_stdout 2>server_stderr &"
Run Code Online (Sandbox Code Playgroud)
也就是说,SSH 命令在服务器停止之前不会返回。放在nohup
前面cd
而不是前面java
没有用。
谁能帮我解决这个问题?你能解释为什么这个解决方案不起作用吗?谢谢!
编辑: cbuckley 建议使用sh -c
,我从中得出:
ssh server "nohup sh -c 'cd /tmp/path && java server 0</dev/null 1>master_stdout 2>master_stderr' 2>/dev/null 1>/dev/null &"
Run Code Online (Sandbox Code Playgroud)
但是,现在退出代码总是0
在cd
失败时;而如果我这样做了,ssh server cd /failed/path
我会得到一个真正的退出代码。建议?
请参阅Bash 的运算符优先级。
将&
被附加到整个语句,因为它具有比更高的优先级&&
。您无需ssh
验证这一点。只需在您的 shell 中运行它:
$ sleep 100 && echo yay &
[1] 19934
Run Code Online (Sandbox Code Playgroud)
如果&
仅附加到echo yay
,那么您的 shell 将休眠 100 秒,然后报告后台作业。但是,整个过程sleep 100 && echo yay
都是后台运行的,您会立即收到工作通知。运行jobs
将显示它挂出:
$ sleep 100 && echo yay &
[1] 20124
$ jobs
[1]+ Running sleep 100 && echo yay &
Run Code Online (Sandbox Code Playgroud)
您可以使用括号在 周围创建一个子shell echo yay &
,为您提供您所期望的:
sleep 100 && ( echo yay & )
Run Code Online (Sandbox Code Playgroud)
这类似于使用bash -c
to run echo yay &
:
sleep 100 && bash -c "echo yay &"
Run Code Online (Sandbox Code Playgroud)
把这些扔进一个ssh
,我们得到:
# using parenthesis...
$ ssh localhost "cd / && (nohup sleep 100 >/dev/null </dev/null &)"
$ ps -ef | grep sleep
me 20136 1 0 16:48 ? 00:00:00 sleep 100
# and using `bash -c`
$ ssh localhost "cd / && bash -c 'nohup sleep 100 >/dev/null </dev/null &'"
$ ps -ef | grep sleep
me 20145 1 0 16:48 ? 00:00:00 sleep 100
Run Code Online (Sandbox Code Playgroud)
将此应用于您的命令,我们得到
ssh server "cd /tmp/path && (nohup java server 0</dev/null 1>server_stdout 2>server_stderr &)"
Run Code Online (Sandbox Code Playgroud)
或者:
ssh server "cd /tmp/path && bash -c 'nohup java server 0</dev/null 1>server_stdout 2>server_stderr &'"
Run Code Online (Sandbox Code Playgroud)
另外,关于您对帖子的评论,
对,
sh -c
总是返回 0。例如,sh -c exit 1
有错误代码 0"
这是不正确的。直接从联机帮助页:
Bash 的退出状态是脚本中执行的最后一个命令的退出状态。如果没有执行任何命令,则退出状态为 0。
的确:
$ bash -c "true ; exit 1"
$ echo $?
1
$ bash -c "false ; exit 22"
$ echo $?
22
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
3316 次 |
最近记录: |