使用双安和(&&)而不是分号(;)时,nohup不起作用

时间:2013-04-10 19:31:24

标签: bash nohup

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

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

此脚本似乎工作正常。但是,当用户输入错误的路径以致cd失败时,它不健壮。由于;,即使nohup失败,此命令也会尝试运行cd命令。

明显的修复不起作用:

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 &"

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

3 个答案:

答案 0 :(得分:4)

请参阅Bash's Operator Precedence

&附加到整个语句,因为它的优先级高于&&。您无需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 &

您可以使用括号创建围绕echo yay &的子shell,为您提供所期望的内容:

sleep 100 && ( echo yay & )

这类似于使用bash -c来运行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

答案 1 :(得分:1)

ssh服务器“test -d / tmp / path”&amp;&amp; ssh服务器“nohup ...&amp;”

答案 2 :(得分:0)

回答综述:

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

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