在试图找出为什么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的正常/预期行为还是错误?
答案 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&)"