我正在使用“&”:为什么该进程不在后台运行?

我正在使用“&”:为什么该进程不在后台运行?

我知道我可以附加&一个命令来在后台运行该进程。

我正在通过 SSH 连接到 Ubuntu 12.04 机器并使用$python program.py &-- 运行 python 程序,但是当我关闭终端窗口时,我收到一条消息,说关闭终端将终止正在运行的进程。

为什么是这样?我正在使用 & 符号在后台运行该进程。无论我是否通过 SSH 连接,如何才能让它运行?

答案1

当您关闭终端窗口时,终端模拟器会向它正在运行的进程(即您的 shell)发送 SIGHUP。然后,您的 shell 将该 SIGHUP 转发给它正在运行的所有内容。在您的本地系统上,这是 ssh。然后 ssh 将 SIGHUP 转发到它正在运行的远程 shell。因此,您的远程 shell 会向其所有进程(您的后台程序)发送 SIGHUP。

有两种方法可以解决这个问题。

  1. 取消后台程序与 shell 的关联。
    1. disown将进程置于后台后使用该命令。这将使 shell 忘记它。
    2. 在命令前加上nohup( nohup $python program.py &)。这完成了同样的事情,但是通过使用中间过程。基本上它会忽略 SIGHUP 信号,然后分叉并执行继承设置的程序,然后退出。因为它是分叉的,所以正在启动的程序不是 shell 的子程序,并且 shell 不知道它。除非它为 SIGHUP 安装信号处理程序,否则它无论如何都会保留忽略操作。
  2. 使用logout(或Ctrl+ d) 而不是关闭终端窗口。当您使用 时logout,这不是 SIGHUP,因此 shell 不会向其任何子级发送 SIGHUP。

此外,您必须确保您的程序不会通过 STDOUT 或 STDERR 写入终端,因为一旦终端退出,这两者都将不再存在。如果你不将它们重定向到类似的东西/dev/null,程序仍然会运行,但如果它尝试写入它们,它会收到一个 SIGPIPE,并且 SIGPIPE 的默认操作是终止进程)。

答案2

该进程在终端后台运行,但stdout(and stderr) 的输出仍在发送到终端。要停止这种情况,请> /dev/null 2>&1&将两个输出重定向到之前添加/dev/null- 添加disown还可以确保关闭终端后该进程不会被终止:

COMMAND > /dev/null 2>&1 & disown

在你的情况下,这将是:

python program.py > /dev/null 2>&1 & disown

答案3

运算&符分隔命令以并行运行,就像;分隔命令以串行运行一样。两种命令仍然会作为 shell 进程的子进程运行

因此,当您关闭启动这些子项的 shell 时,这些子项也将被关闭。

你似乎想要的是守护进程,这要棘手得多,因为它需要完全与父进程分离。 shell 通常没有简单的方法来做到这一点。

答案4

在以 & 符号 ( ) 结尾的命令之后&,在命令提示符处运行以下命令bg

bash> python program.py &  
bash> bg  

这会将“&”命令置于后台

bash> jobs  

这将列出在后台运行的作业

bash> fg 1   

这会将作业 #1 带到前台

另一种方式,(能够注销)

bash> at now  
bash> /full/path/python /full/path/program.py  
bash> ^d   `(# That is, Control-D, to run the command, Control-C to cancel)`  

可以提交多行命令at,在 ^d (Control-D) 之前
参见man at

相关内容