5

我有一个脚本,用于ssh登录到远程机器、cd特定目录,然后启动一个守护进程。原始脚本如下所示:

ssh server "cd /tmp/path ; nohup java server 0</dev/null 1>server_stdout 2>server_stderr &"

这个脚本似乎工作正常。但是,当用户输入错误的路径导致cd失败时,它并不可靠。由于 ,即使失败;,该命令也会尝试运行该命令。nohupcd

明显的修复不起作用:

ssh server "cd /tmp/path && nohup java server 0</dev/null 1>server_stdout 2>server_stderr &"

也就是说,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 &"

但是,现在退出代码总是0cd失败时;而如果我这样做,ssh server cd /failed/path那么我会得到一个真正的退出代码。建议?

4

3 回答 3

5

请参阅Bash 的运算符优先级

&附加到整个语句,因为它的优先级高于&&. 您无需对此ssh进行验证。只需在你的 shell 中运行它:

$ sleep 100 && echo yay &
[1] 19934

如果&仅附加到echo yay,那么您的 shell 将休眠 100 秒,然后报告后台作业。但是,整个过程sleep 100 && echo yay都是后台运行的,您会立即收到工作通知。运行jobs将显示它挂出:

$ sleep 100 && echo yay &
[1] 20124
$ jobs
[1]+  Running                 sleep 100 && echo yay &

您可以使用括号在 周围创建一个子shell echo yay &,为您提供您所期望的:

sleep 100 && ( echo yay & )

这类似于 using bash -cto run echo yay &

sleep 100 && bash -c "echo yay &"

把这些扔进一个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

将此应用于您的命令,我们得到

ssh server "cd /tmp/path && (nohup java server 0</dev/null 1>server_stdout 2>server_stderr &)"

或者:

ssh server "cd /tmp/path && bash -c 'nohup java server 0</dev/null 1>server_stdout 2>server_stderr &'"

另外,关于你对帖子的评论,

对,sh -c总是返回 0。例如,sh -c exit 1错误代码为 0"

这是不正确的。直接从手册页:

Bash 的退出状态是脚本中执行的最后一个命令的退出状态。如果没有执行任何命令,则退出状态为 0。

确实:

$ bash -c "true ; exit 1"
$ echo $?
1
$ bash -c "false ; exit 22"
$ echo $?
22
于 2013-04-17T22:58:52.927 回答
1

ssh 服务器 "test -d /tmp/path" && ssh 服务器 "nohup ... &"

于 2013-04-12T08:26:04.717 回答
0

答案汇总:

  • 坏:sh -c用于包装整个nohup命令对我的目的不起作用,因为它不返回错误代码。(@cbuckley)
  • 好的:ssh <server> <cmd1> && ssh <server> <cmd2>工作但速度慢得多(@joachim-nilsson)
  • 好:创建一个shell脚本<server>,连续运行命令并返回正确的错误代码。

最后一个是我最终使用的。如果了解外壳内部原理的人可以向我解释,我仍然有兴趣了解为什么原始用例不起作用!

于 2013-04-17T20:34:36.433 回答