(bash) 脚本 A,等待脚本 B,但不等待它的子进程

Apo*_*poc 9 bash ssh background-process

所以我有 scriptA 它可以:

ssh server1 -- scriptB &
ssh server2 -- scriptB &
ssh server3 -- scriptB &
wait
otherstuffhappens
Run Code Online (Sandbox Code Playgroud)

ScriptB 执行以下操作:

rsync -av /important/stuff/. remoteserver:/remote/dir/.
rsync -av /not/so/important/stuff/. remoteserver:/remote/dir/. &
exit
Run Code Online (Sandbox Code Playgroud)

我想要的结果是 scriptA 将在继续之前等待 scriptB 的所有实例完成,它目前正在这样做,但是它也在等待不那么重要的东西的后台 rsyncs。这些是我不想等待的较大文件。

我已经阅读了nohup、disown 和 & 之间的差异并尝试了不同的组合,但我没有得到我想要的结果。

在这一点上,我很难过。任何帮助,将不胜感激!

Sté*_*las 15

这里的问题是sshd等待管道上的文件结束,它正在从中读取命令的标准输出(由于某种原因而不是标准输出,至少在我正在测试的版本中)。后台作业继承了该管道的 fd。

因此,要解决这个问题,请将后台rsync命令的输出重定向到某个文件,或者/dev/null如果您不关心它。您还应该重定向 stderr,因为即使 sshd 没有等待相应的管道,sshd退出后,管道也会被破坏,因此rsync如果它尝试在 stderr 上写入,则会被杀死。

所以:

rsync ... > /dev/null 2>&1 &
Run Code Online (Sandbox Code Playgroud)

相比:

$ time ssh localhost 'sleep 2 &'
ssh localhost 'sleep 2 &'  0.05s user 0.00s system 2% cpu 2.365 total
$ time ssh localhost 'sleep 2 > /dev/null &'
ssh localhost 'sleep 2 > /dev/null &'  0.04s user 0.00s system 12% cpu 0.349 total
Run Code Online (Sandbox Code Playgroud)

和:

$ ssh localhost '(sleep 1; ls /x; echo "$?" > out) > /dev/null &'; sleep 2; cat out
141  # ls by killed with SIGPIPE upon writing the error message
$ ssh localhost '(sleep 1; ls /x; echo "$?" > out) > /dev/null 2>&1 &'; sleep 2; cat out
2    # ls exited normally after writing the error on /dev/null instead
     # of a broken pipe
Run Code Online (Sandbox Code Playgroud)