从 Sh(不是 Bash)中分离进程或“解除”Sh(不是 Bash)

从 Sh(不是 Bash)中分离进程或“解除”Sh(不是 Bash)

考虑由 Sh 而不是 Bash 执行的 shell 脚本(我无法更改它,也无法使用 shebang,它会被忽略)。接线员&工作,但disown $!不工作,让 Sh 抱怨“否认:未找到”。

如何从特定的 Sh 中分离后台进程?我的意思是,从 Sh 中执行的操作与disown从 Bash 中执行的操作相同。

答案1

首先让我们看看 Bash 的disown命令做了什么。从bash手册:

shell 在收到SIGHUP.在退出之前,交互式 shell 会重新SIGHUP向所有正在运行或已停止的作业发送 。发送停止的作业SIGCONT以确保它们收到SIGHUP.为了防止 shell 将SIGHUP信号发送到特定作业,应使用 disown 内置函数将其从作业表中删除(请参阅作业控制内置函数)或SIGHUP使用标记为不接收disown -h

如果huponexit已设置 shell 选项shopt(请参阅内置 Shopt),则SIGHUP当交互式登录 shell 退出时,Bash 会向所有作业发送 a 。

这意味着它是 shell 本身,如果它接收到SIGHUP,则将其转发到后台作业。如果 shell 退出(并且huponexit尚未启用),则没有控制终端的后台进程不会SIGHUP关闭终端。

因此,如果您关心的是阻止SIGHUP从 shell 包装器启动的进程,例如

#!/bin/sh
my-command arg &

那么就不需要disown类似的功能,因为除非 shell 在退出之前获取它,否则my-command不会接收。SIGHUP

但是,如果您想从脚本运行子级,该脚本在启动子级后将继续执行一段时间,仍然存在问题,如下所示:

#!/bin/sh
sleep 55555 &
sleep 3333 # some long operation we don't care about

sleep 55555如果脚本的控制终端关闭,上面的脚本将终止命令。由于 Bourne shell 没有disownBash、Ksh 和其他一些 shell 所具有的内置功能,因此我们需要另一个工具。那个工具是nohup(1)。上面的脚本,我们对子进程的stdout和不感兴趣stderr,可以修改为以下内容以避免sleep获取SIGHUP

#!/bin/sh
nohup sleep 55555 >/dev/null 2>&1 &
sleep 3333 # some long operation we don't care about

重定向到/dev/null是为了避免nohup.out在当前目录中获取文件。如果没有重定向,此文件将包含 nohupped 进程的输出。

相关内容