我正在使用`&`:为什么该进程未在后台运行?


24

我知道我可以追加&命令以在后台运行该过程。

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

为什么是这样?我正在使用&符在后台运行该过程。无论我是否使用SSH,如何才能使其运行?



apt-get安装屏幕,手动屏幕

Answers:


51

当您关闭终端窗口时,终端仿真器会将SIGHUP发送到它正在运行的进程,即Shell。然后,您的shell将SIGHUP转发到它正在运行的所有内容。在您的本地系统上,这是ssh。然后,ssh将SIGHUP转发到它正在运行的远程外壳。因此,您的远程外壳程序随后将SIGHUP发送到其所有进程,即后台程序。

有两种解决方法。

  1. 取消后台程序与Shell的关联。
    1. 使disown进程后台运行后,使用该命令。这会使外壳忘记它。
    2. 在命令前面加上nohupnohup $python program.py &)。这可以完成相同的操作,但是要使用中间过程。基本上,它会忽略SIGHUP信号,然后派生并执行继承设置的程序,然后退出。因为它是分叉的,所以启动的程序不是外壳程序的子级,外壳程序也不知道它。除非它为SIGHUP安装了信号处理程序,否则它将始终保持忽略操作。
  2. 使用logout而不是关闭终端窗口。使用时logout,这不是SIGHUP,因此外壳程序不会将SIGHUP发送给它的任何子级。

另外,您必须确保您的程序不会通过STDOUT或STDERR写入终端,因为一旦终端退出,这两个都将不再存在。如果你不把它们重新导向到像/dev/null,该程序将继续运行,但如果它试图对其进行写操作,它会得到一个SIGPIPE和SIGPIPE的默认动作是终止进程)。


4
从技术上讲,ssh染色会导致连接断开,连接下降会导致sshd另一端死亡。该sshd控制着远程外壳运行的伪终端的主端,当它死亡时,这是一个挂断(就像拔掉真实终端上的插头一样),因此系统将SIGHUP发送到远程外壳。
斯特凡Chazelas

@StéphaneChazelas这是我从未研究过的一件事。如果是内核在做,它如何确定SIGHUP使用哪个进程?显然,它不会用TTY的打开文件描述符来标记所有内容,因为只要程序不尝试使用它,它们就会一直运行。那么,它是否选择了当前正在从STDIN读取的程序(因为一次只能从STDIN读取一个程序)?
帕特里克

4
没关系,回答了我自己的问题。POSIX IEEE 1003.1第11章,如果控制终端的终端接口检测到调制解调器断开连接,则应将SIGHUP信号发送到控制过程
帕特里克

2
另请注意,nohupnohup.out文件将生成一个文件,其中包含您以该文件开头的程序的输出。每次使用nohup以这种方式启动应用程序时,删除该文件可能会很烦人(否则您需要将其输出重定向到/dev/null)。
Ruslan 2014年

1
相反,nohup python program.py &我建议您使用setsid python program.py替代方法,它会立即使程序放弃。
Hitechcomputergeek

14

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

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

在您的情况下,这将是:

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

3

&操作中隔离命令并行运行,就像;中隔离命令串联运行。两种命令仍将作为Shell进程的子进程运行

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

您似乎想要的是一个守护进程,它要复杂得多,因为它需要与父进程完全分离。外壳通常没有简单的方法。


1

注销时,通常也会杀死与登录会话关联的后台进程。如果希望它们与会话断开连接,请使用运行它们nohup

nohup python program.py &

1

在以&符号(&)结尾的命令之后,在命令提示符处运行命令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之前命令,(控制-d)
看到man at

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.