我正在发现nohup
Ubuntudisown
的bash
.
我有while.py
。
import time
while True:
print(1)
time.sleep(1)
首先,我使用 ssh 连接到我的 ubuntu 服务器并输入nohup python3 while.py &
.然后我进入exit
退出终端。重新连接服务器并输入后ps aux | grep python
,我可以清楚地看到进程正在运行。然后我杀掉这个进程。
第二,我进入了python3 while.py & disown
。程序开始1
在 shell 中打印。然后我退出 shell 并重新连接到服务器。但是,当我输入 时ps aux | grep python
,我看不到进程正在运行。
似乎否认并没有阻止进程在关闭终端后被终止。我已经搜索过相关问题。塞尔奇克提到disown
确保 shell 不会向它发送 SIGHUP 并且nohup
确保进程不会收到任何发送的 SIGHUP。这个答案提到终端在关闭时向所有进程发送 SIGHUP、SIGCONT、SIGCHID。因此我有一个问题,为什么 nohup 和 disown 在关闭终端后表现不同。
英语不是我的母语。如果存在语法错误,请原谅。如果您能提供帮助,我将不胜感激。
答案1
在unix最初的硬件环境中,“终端”是一个连接到串行端口的硬件。这可以是实际的终端或电话线上的调制解调器或类似的东西。
如果您使用远程调制解调器呼叫调制解调器并连接,则您将登录到系统。当您断开连接(“挂断”)时,系统会向连接到串行端口的所有设备发送 HUP。然后,系统会将 HUP 信号(请参阅 参考资料man -s 7 signal
)发送到连接到该串行端口的每个进程,以清除它们并使该端口可供下一个用户使用。如果您退出物理终端,这也会模拟挂断。
串行端口仍然存在,但大多数“终端”现在都是虚拟的,以软件实现,并通过伪终端 (pty) 接口进行连接。但这仍然与串行端口几乎相同。伪终端有两个接口:一个是终端软件连接的主接口,另一个是客户端,其作用类似于外部串行端口的软件端。
当主 pty 关闭(可能通过关闭窗口或断开 ssh 连接)或发生任何数量的其他操作时,这会触发调制解调器挂断会触发的相同事件,向连接到终端的每个进程发送 HUP 信号。
该nohup
命令阻止进程接收 HUP 信号,因此它不会被直接杀死。但是,它可能仍然有连接到终端的标准输入和标准输出。 master pty 关闭后,stdin 和 stdout 将被有效地替换为 /dev/null,这可能会导致进程在尝试读取时在 stdin 上收到 EOF,这仍然可能导致其退出。
如果 shell 有后台作业并且您退出 shell,它通常会尝试使用 HUP 信号杀死它所知道的作业,以在其自身之后进行清理。该disown
命令告诉 shell 忘记其作业控制列表中的作业。但这并不会解除作业中的进程与终端的关联,终端可能仍会尝试摆脱它们。
答案2
我已经发现问题的原因了。这个答案提到
如果终端是被摧毁(如果它是一个 pty,就像 xterm 或 ssh 创建的 pty,并且通过关闭 xterm 或终止 SSH 连接来终止控制程序,则可能会发生这种情况),程序将失败一旦它尝试从标准输入读取或者写入标准输出。
终端退出后, disown 不会断开与stdout
或 的连接stderr
。我的程序print(1)
,它尝试写入stdout
并导致程序崩溃。
为了解决这个问题,我们只需要重定向stdout
并stderr
通过python3 while.py >/dev/null 2>&1 & disown
答案3
disown 会从 shell 的作业控制中删除该进程,该进程仍将附加到终端会话 - 因此,当您退出终端时,该进程将会终止。