nohup什么时候关闭终端结束后台运行的进程不起作用?

it_*_*ure 8 bash nohup

nohup command &可以在关闭终端后保持命令运行。我想播放目录中的所有 mp3 音乐Music

ls Music/*mp3 |xargs -d "\n" mplayer  
Run Code Online (Sandbox Code Playgroud)

ls Music/*mp3可以列出目录中的所有mp3文件,Music通过带有xargs的管道发送,-d "\n"是处理文件名中的空白。

我想将 allstdout和重定向stderr/dev/null,并在后台运行它。

ls Music/*mp3 |xargs -d "\n" mplayer > /dev/null 2>&1 &
Run Code Online (Sandbox Code Playgroud)

这工作正常,但我希望它在关闭终端后运行。

nohup ls Music/*mp3 | xargs -d "\n" mplayer > /dev/null 2>&1 &
ls Music/*mp3 | xargs -d "\n" nohup mplayer > /dev/null 2>&1 &
ls Music/*mp3 | nohup xargs -d "\n" mplayer > /dev/null 2>&1 &
Run Code Online (Sandbox Code Playgroud)

当我关闭终端时,后台运行的进程结束。
为什么nohup在以上三个命令中没有一个生效?我怎样才能让它生效?

disown可以解决问题,但我想要一个使用nohup.

ls Music/*mp3 | xargs -d "\n" mplayer > /dev/null 2>&1 & disown
Run Code Online (Sandbox Code Playgroud)

dim*_*414 9

nohup command意思是“运行command并忽略HUP 信号”。

所以在我们可以有效使用之前,我们nohup需要问:何时以及如何SIGHUP发送?正如 Bash 手册所说,“在退出之前,交互式 shell 会将 SIGHUP 重新发送给所有正在运行或已停止的作业。” . 它接着说,抑制这种行为的正确方法是使用disown. 我知道您在询问nohup,但值得一提的disown是,这是实现您想要的目标的有意且更简单的方法。请注意,disown不是等同于nohup

nohup这里使用的原因很棘手,因为它适用于单个进程,而&创建了整个命令管道的后台作业,它可以由多个进程组成。这意味着您需要管道中的每个命令以确保单个命令不会收到 SIGHUP,例如:nohup

$ nohup ls Music/*mp3 2>/dev/null | nohup xargs -d "\n" nohup mplayer &> /dev/null &
Run Code Online (Sandbox Code Playgroud)

应该可以工作,尽管我还没有使用这些特定命令对其进行测试。如果不是,则可能是您未直接启动的另一个进程仍在接收 SIGHUP。这更难解决,这正是我们拥有disown.

manishg的建议也有道理;通过将管道移动到一个单独的进程中,您可以执行nohup 进程,这反过来应该会阻止 SIGHUP 在您的 shell 关闭时到达其子进程。


所有这一切,首先你不需要lsxargs在这里;find可以用于类似的效果,并将简化对命令的推理。尝试:

$ nohup find Music -maxdepth 1 -name '*mp3' -exec mplayer {} + &> /dev/null &
Run Code Online (Sandbox Code Playgroud)