d-b*_*d-b 14 zsh background-process
我想在后台相继运行两个 shell 脚本,最好也使用nohup
.
我从
% nohup a.sh &
Run Code Online (Sandbox Code Playgroud)
a
这在后台运行。
% nohup a.sh && nohup b.sh
Run Code Online (Sandbox Code Playgroud)
运行a
然后b
(如果a
成功)
但如何在后台启动最后一个组合呢?
如果我做
% nohup a.sh && nohup b.sh &
Run Code Online (Sandbox Code Playgroud)
a
将在前台运行,阻止提示符,然后b
在后台启动,将控制权返回给提示符。
% nohup a.sh & && nohup b.sh &
Run Code Online (Sandbox Code Playgroud)
这给出了一个错误:zsh: parse error near '&&'
如何在后台启动两个进程?
Sté*_*las 27
这是 zsh 与 sh(或 csh)相比的已知偏差之一。
\n在sh中:
\nA && B &\n
Run Code Online (Sandbox Code Playgroud)\n是缩写:
\n(A && B) &\n
Run Code Online (Sandbox Code Playgroud)\n也就是说,它运行一个子 shell,该子 shell 在后台/异步运行该和/或列表。
\n在 zsh 中,
\nA && B &\n
Run Code Online (Sandbox Code Playgroud)\n同步运行A
,等待,如果成功,则B
在后台/异步运行。
其手册中对此进行了说明(请参阅 参考资料info zsh list
):
\n\n列表是零个或多个子列表的序列,其中每个子列表都以、
\n;
、&
、&|
或&!
换行符结尾。当列表作为复杂命令出现在(...)
或中时,可以选择从列表中的最后一个子列表中省略此终止符{...}
。当子列表由;
或 换行符终止时,shell 会等待其完成,然后再执行下一个子列表。 如果子列表由&
、&|
或终止&!
,则 shell 在后台执行其中的最后一个管道,并且不等待它完成(请注意与在后台执行整个子列表的其他 shell 的区别)。后台管道\n返回状态为零。
(强调我的)。
\n在常见问题解答中:
\n\n\n在 zsh中
\ncmd1 && cmd2 &
,仅cmd2
而不是整个表达式在后台运行。该手册暗示这是一个错误。用作{ cmd1 && cmd2 } &
解决方法。
A && B
要像其他 shell 一样在后台运行子 shell ,请使用:
(A && B) &\n
Run Code Online (Sandbox Code Playgroud)\n或者按照常见问题解答条目的建议:
\n{A && B} &\n
Run Code Online (Sandbox Code Playgroud)\n这是等效的,因为如果必须异步运行,我们无论如何都需要派生一个进程(并且主 shell 进程同时继续执行脚本的其余部分)。
\n所以在这里:
\n(nohup a.sh && nohup b.sh) &\n
Run Code Online (Sandbox Code Playgroud)\n不过,如果您只是希望运行该子 shell 的进程及其生成的其他进程不受 SIGHUP 信号的影响:
\n(trap \'\' HUP; A && B) &\n
Run Code Online (Sandbox Code Playgroud)\n(您还可以添加一些< /dev/null >> nohup.out 2>&1
以更接近地模仿 nohup)
相反,如果您希望在其他类似 sh 的 shell 中获得与 zsh 相同的行为:
\nA && { B & }\n
Run Code Online (Sandbox Code Playgroud)\n(请记住,在 zsh 以外的 shell 中,当未启用作业控制时,异步运行的列表的 stdin 会重定向到 /dev/null)
\n\xc2\xb9 偏差可能是无意的,因为2000 年之前的文档措辞进行了更改以修复它以与实际行为保持一致(这可以追溯到 1990 年的 zsh 1.0)描述了嘘行为。这也是自 1997 年以来“手册暗示这是一个错误” 的常见问题解答的结论。但现在改变它已经太晚了(但有人认为应该在 sh、csh 或 ksh 模拟中改变它)。
\n您必须将这两个命令组合在一起:
nohup sh -c 'a.sh; b.sh' &
Run Code Online (Sandbox Code Playgroud)
如果您只想在成功退出时运行,请替换;
为&&
b.sh
a.sh