程序后台运行
作者:
| 更新日期:以前知道nohup可以使初次运行的程序后台运行, 但是其他情况的程序就没办法了, 这里完善的记录一下各种情况后台运行的操作.
本文首发于公众号:天空的代码世界,微信号:tiankonguse
背景
经常会遇到这样一个问题, ssh登陆远程服务器, 运行一些程序. 后来退出时没跑完的程序也退出了.
即使我们加上&
命令, 没跑完的程序依旧退出.
这篇文章就记录我们该如何让程序后台运行, 我们ssh退出的时候程序不退出.
原因
我们ssh登陆后, 运行的程序都是当前登陆会话的子进程.
会话关闭后, 子进程都被关闭了.
所以解决方案就是让后台运行的进程不是当前会话的子进程.
启动时转后台
### nohup
nohup 是我最常用的手法.
nohup 的作用就是忽略hangups
信号.
使用简单, 直接放在命令前面即可.
默认标准输出和标准错误缺省会被重定向到 nohup.out 文件中。
一般我们可在结尾加上&
来将命令同时放入后台运行,也可用>filename 2>&1
来更改缺省的重定向文件名。
# nohup - run a command immune to hangups, with output to a non-tty
nohup myapp --start > ../log/some.log 2>&1 &
setsid
setsid
的功能是创建一个新会话, 也能满足我们的要求.
# setsid - run a program in a new session
setsid myapp --start > ../log/some.log 2>&1 &
shell小技巧
我们知道,将一个或多个命名包含在()
中就能让这些命令在子 shell 中运行中,从而扩展出很多有趣的功能,我们现在要讨论的就是其中之一。
当我们将&
也放入()
内之后,我们就会发现所提交的作业并不在作业列表中,也就是说,是无法通过jobs来查看的。
让我们来看看为什么这样就能躲过 HUP 信号的影响吧。
(myapp --start > ../log/some.log 2>&1 &)
运行中转后台
有时候我们的任务已经在运行了. 现在我们需要关闭会话, 但是不想停止任务.
这个时候就需要这个小节的知识点了.
disown处理任务
disown [-ar] [-h] [jobspec ...]
Without options, each jobspec is removed from the table of active jobs.
If jobspec is not present, and neither -a nor -r is supplied, the shell’s notion of the current job is used.
If the -h option is given, each jobspec is not removed from the table, but is marked so that SIGHUP is not sent to the job if the shell receives a SIGHUP.
If no jobspec is present, and neither the -a nor the -r option is supplied, the current job is used.
If no jobspec is supplied, the -a option means to remove or mark all jobs;
the -r option without a jobspec argument restricts operation to running jobs.
The return value is 0 unless a jobspec does not specify a valid job.
可以看出,我们可以用如下方式来达成我们的目的。
- 用
disown -h jobspec
来使某个作业忽略HUP信号。 - 用
disown -ah
来使所有的作业都忽略HUP信号。 - 用
disown -rh
来使正在运行的作业忽略HUP信号。
需要注意的是,当使用过 disown 之后,会将把目标作业从作业列表中移除,我们将不能再使用jobs来查看它,但是依然能够用ps -ef
查找到它。
正在运行中的任务
可以参考我14年的一篇文章ubuntu 前台程序和后台程序.
我们可以把任务转为后台任务, 然后就可以再使用 disown 来转化为后台程序了.
screen
我们已经知道了如何让进程免受 HUP 信号的影响,但是如果有大量这种命令需要在稳定的后台里运行,如何避免对每条命令都做这样的操作呢?
此时最方便的方法就是 screen 了。
screen 的参数很多,具有很强大的功能,我们在此仅介绍其常用功能以及简要分析一下为什么使用 screen 能够避免 HUP 信号的影响。
NAME
screen - screen manager with VT100/ANSI terminal emulation
SYNOPSIS
screen [ -options ] [ cmd [ args ] ]
screen -r [[pid.]tty[.host]]
screen -r sessionowner/[[pid.]tty[.host]]
DESCRIPTION
Screen is a full-screen window manager that multiplexes a physical
terminal between several processes (typically interactive shells).
Each virtual terminal provides the functions of a DEC VT100 terminal
and, in addition, several control functions from the ISO 6429 (ECMA
48, ANSI X3.64) and ISO 2022 standards (e.g. insert/delete line and
support for multiple character sets). There is a scrollback history
buffer for each virtual terminal and a copy-and-paste mechanism that
allows moving text regions between windows.
使用 screen 很方便,有以下几个常用选项:
- 用
screen -dmS session name
来建立一个处于断开模式下的会话(并指定其会话名)。 - 用
screen -list
来列出所有会话。 - 用
screen -r session name
来重新连接指定会话。 - 用快捷键
CTRL-a d
来暂时断开当前会话。
当我们用-r
连接到 screen 会话后,我们就可以在这个伪终端里面为所欲为,再也不用担心 HUP 信号会对我们的进程造成影响,也不用给每个命令前都加上nohup
或者setsid
了。
总结
现在几种方法已经介绍完毕,我们可以根据不同的场景来选择不同的方案。
nohup/setsid
无疑是临时需要时最方便的方法,disown
能帮助我们来事后补救当前已经在运行了的作业,而screen
则是在大批量操作时不二的选择了。
本文首发于公众号:天空的代码世界,微信号:tiankonguse
如果你想留言,可以在微信里面关注公众号进行留言。