我知道我可以附加&
一个命令来在后台运行该进程。
我正在通过 SSH 连接到 Ubuntu 12.04 机器并使用$python program.py &
-- 运行 python 程序,但是当我关闭终端窗口时,我收到一条消息,说关闭终端将终止正在运行的进程。
为什么是这样?我正在使用 & 符号在后台运行该进程。无论我是否通过 SSH 连接,如何才能让它运行?
答案1
当您关闭终端窗口时,终端模拟器会向它正在运行的进程(即您的 shell)发送 SIGHUP。然后,您的 shell 将该 SIGHUP 转发给它正在运行的所有内容。在您的本地系统上,这是 ssh。然后 ssh 将 SIGHUP 转发到它正在运行的远程 shell。因此,您的远程 shell 会向其所有进程(您的后台程序)发送 SIGHUP。
有两种方法可以解决这个问题。
- 取消后台程序与 shell 的关联。
disown
将进程置于后台后使用该命令。这将使 shell 忘记它。- 在命令前加上
nohup
(nohup $python program.py &
)。这完成了同样的事情,但是通过使用中间过程。基本上它会忽略 SIGHUP 信号,然后分叉并执行继承设置的程序,然后退出。因为它是分叉的,所以正在启动的程序不是 shell 的子程序,并且 shell 不知道它。除非它为 SIGHUP 安装信号处理程序,否则它无论如何都会保留忽略操作。
- 使用
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
。