在后台运行两个脚本? && 和 & 不起作用?

在后台运行两个脚本? && 和 & 不起作用?

我想在后台相继运行两个 shell 脚本,最好也使用nohup.

我从

% nohup a.sh &

a在后台运行。

% nohup a.sh && nohup b.sh

运行a然后b(如果a成功)

但如何在后台启动最后一个组合呢?

如果我做

% nohup a.sh && nohup b.sh &

a将在前台运行,阻止提示符,然后b在后台启动,将控制权返回给提示符。

% nohup a.sh & && nohup b.sh &

这给出了一个错误:zsh: parse error near '&&'

如何在后台启动两个进程?

答案1

这是 zsh 与 sh(或 csh)相比的已知偏差之一。

在sh中:

A && B &

是缩写:

(A && B) &

也就是说,它运行一个子 shell,该子 shell 在后台/异步运行该和/或列表。

在 zsh 中,

A && B &

同步运行A,等待,如果成功,则B在后台/异步运行。

那是其手册中注明(看info zsh list):

A列表;是零个或多个子列表的序列,其中每个子列表以、&&|&!或换行符终止。当列表作为复杂命令出现在(...)或中时,可以选择从列表中的最后一个子列表中省略该终止符{...}。当子列表由 或 换行符终止时;,shell 会等待它完成,然后再执行下一个子列表。 &如果子列表以、&|或终止&!,则 shell 会在后台执行其中的最后一个管道,并且不会等待它完成(请注意与在后台执行整个子列表的其他 shell 的区别)。后台管道返回零状态。

(强调我的)。

在常见问题解答中:

在zsh 中cmd1 && cmd2 &,仅cmd2而不是整个表达式在后台运行。该手册暗示这是一个错误。用作{ cmd1 && cmd2 } &解决方法。

A && B要像其他 shell 一样在后台运行子 shell ,请使用:

(A && B) &

或者按照常见问题解答条目的建议:

{A && B} &

这是等效的,因为如果必须异步运行,我们无论如何都需要派生一个进程(并且主 shell 进程同时继续执行脚本的其余部分)。

所以在这里:

(nohup a.sh && nohup b.sh) &

不过,如果您只是希望运行该子 shell 的进程及其生成的其他进程不受 SIGHUP 信号的影响:

(trap '' HUP; A && B) &

(您还可以添加一些< /dev/null >> nohup.out 2>&1以更接近地模仿 nohup)

相反,如果您希望在其他类似 sh 的 shell 中获得与 zsh 相同的行为:

A && { B & }

(请记住在 zsh 以外的 shell 中,当未启用作业控制时,异步运行的列表的 stdin 会重定向到 /dev/null


1 偏差可能是无意的,因为之前文档的措辞2000 年进行的更改修复了它以符合实际行为(这可以追溯到 1990 年的 zsh 1.0)描述了 sh 行为。这也是常见问题解答的结论“手册暗示这是一个错误” 自1997年以来。但现在改变它已经太晚了(但有人认为应该在 sh、csh 或 ksh 模拟中改变它)。

答案2

您必须将这两个命令组合在一起:

nohup sh -c 'a.sh; b.sh' &

如果您只想在成功退出时运行,请替换;&&b.sha.sh

相关内容