考虑由 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 没有disown
Bash、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 进程的输出。