我有一个脚本,用于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 -cto 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 次 |
| 最近记录: |