bash&&运算符阻止ssh上的背景

时间:2012-03-29 16:19:31

标签: bash ssh background-process

在试图找出为什么Capistrano任务(试图在后台启动守护程序)挂起之后,我发现在bsh中使用&&阻止后续程序在后台运行。我在bash 4.1.5和4.2.20上尝试过它。

以下内容将在bash中挂起(即等待sleep完成):

ssh localhost "cd /tmp && nohup sleep 10 >/dev/null 2>&1 &"

以下不会:

ssh localhost "cd /tmp ; nohup sleep 10 >/dev/null 2>&1 &"

这也不会:

cd /tmp && nohup sleep 10 >/dev/null 2>&1 &

zsh和dash都会在所有情况下在后台执行它,无论&&和ssh如何。这是bash的正常/预期行为还是错误?

2 个答案:

答案 0 :(得分:4)

一个简单的解决方案是使用:

ssh localhost "(cd /tmp && nohup sleep 10) >/dev/null 2>&1 &"

(如果你使用大括号也可以,见下面的第二个例子。)

我没有进一步尝试,但我有理由相信它与悬挂的打开文件描述符有关。也许zsh和dash绑定&&,这意味着必须拼写为:

{ cd /tmp && nohup sleep 10; } >/dev/null 2>&1
bash中的


没有,快速实验短划线显示echo foo && echo bar >file仅重定向后者。但是,它必须与延迟打开fd导致ssh等待更多输出有关;我过去经常遇到这种情况。
如果对这个特定情况使用括号或大括号,则不需要另外一个技巧,但在更一般的上下文中可能会有用,其中与&&相关的命令集更复杂。由于bash似乎与&&不恰当地挂在文件描述符上,而不是;,因此您可以将a && b && c转换为a || exit 1; b || exit 1; c。这适用于测试用例:

ssh localhost "true || exit 1; echo going on; nohup sleep 10 >/dev/null 2>&1 &"

true替换为false,省略“继续”的回显。

(你也可以set -e,虽然有时这是一个比预期更大的锤子。)

答案 1 :(得分:1)

这似乎有效:

ssh localhost "(exec 0>&- ; exec 1>&-; exec 2>&-; cd /tmp; sleep 20&)"