参考: http://www.dedecms.com/knowledge/servers/linux-bsd/2012/0822/12830.html
Unix/Linux下一般想让某个程序在后台运行,很多都是使用 & 在程序结尾来让程序自动运行. 但是我们很多程序并不可以做成守护进程,可能我们的程序只是普通程序而已,一般这种程序即使使用 & 结尾,如果终端关闭,那么程序也会被关闭。 关闭ssh连接(关掉窗口/断开连接)后会使得正在运行的程序死掉的元凶是 SIGHUP 信号。在Linux/Unix中,有这样几个概念:
- 进程组(process group):一个或多个进程的集合,每一个进程组有唯一一个进程组ID,即进程组长进程的ID。
- 会话期(session):一个或多个进程组的集合,有唯一一个会话期首进程(session leader)。会话期ID为首进程的ID。
- 会话期可以有一个单独的控制终端(controlling terminal)。与控制终端连接的会话期首进程叫做控制进程(controlling process)。当前与终端交互的进程称为前台进程组。其余进程组称为后台进程组。
根据POSIX.1定义:
- 挂断信号(SIGHUP)默认的动作是终止程序。
- 当终端接口检测到网络连接断开,将挂断信号发送给控制进程(会话期首进程)。
- 如果会话期首进程终止,则该信号发送到该会话期前台进程组。
- 一个进程退出导致一个孤儿进程组中产生时,如果任意一个孤儿进程组进程处于STOP状态,发送SIGHUP和SIGCONT信号到该进程组中所有进程。
因此当网络断开或终端窗口关闭后,控制进程收到SIGHUP信号退出,会导致该会话期内其他进程退出。
为了能够后台运行,我们可以忽略SIGHUP信号,关掉窗口应该就不会影响程序的运行了。nohup命令可以达到这个目的,如果程序的标准输出/标准错误是终端, nohup默认将其重定向到nohup.out文件。值得注意的是nohup命令只是使得程序忽略SIGHUP信号,还需要使用标记&把它放在后台运行。我们需要使用nohup这个命令, 比如我们有个start.sh需要在后台运行,并且希望在后台能够一直运行,那么就使用nohup:语法格式为 nohup <command> [argument...] &如 nohup /root/start.sh
在shell中回车后提示:
[~]$ appending output to nohup.out
原程序的的标准输出被自动改向到当前目录下的nohup.out文件,起到了log的作用。
但是有时候在这一步会有问题,当把终端关闭后,进程会自动被关闭,察看nohup.out可以看到在关闭终端瞬间服务自动关闭。
注意:是在当shell中提示了nohup成功后还需要按终端上键盘任意键退回到shell输入命令窗口,然后通过在shell中输入exit来退出终端;
而在nohup执行成功后直接点关闭程序按钮关闭终端.会出现上面的问题。所以这时候会断掉该命令所对应的session,导致nohup对应的进程被通知需要一起shutdown。
如果想在关闭ssh连接后刚才启动的程序继续运行怎么办,可以使用nohup。但是如果要求第二天来的时候,一开ssh,还能查看到昨天运行的程序的状态,
然后继续工作,这时nohup是不行了,需要使用screen来达到这个目的。
1)使用
执行 screen , 按任意键进入子界面;
我用ping命令开始执行,如果下班了,但是想关闭ssh以后ping继续运行,那么按ctrl+a 再按 d 这样暂停了子界面,会显示[detached]的字样,这时候 我回到了父界面;
用screen –ls查看目前子界面的状态 screen -ls
There is a screen on: 22292.pts-3.free (Detached)
1 Socket in /tmp/screens/S-root,这里的22292其实是子界面的pid号;
如果回到子界面 用 screen –r 22292,一下子弹到了ping 的子界面;
2)更多帮助
可以通过C-a(ctrl+a)?来查看所有的键绑定,常用的键绑定有:
C-a ?
显示所有键绑定信息
C-a w
显示所有窗口列表
C-a C-a
切换到之前显示的窗口
C-a c
创建一个新的运行shell的窗口并切换到该窗口
C-a n
切换到下一个窗口
C-a p
切换到前一个窗口(与C-a n相对)
C-a 0..9
切换到窗口0..9
C-a a
发送C-a到当前窗口
C-a d
暂时断开screen会话
C-a k
杀掉当前窗口
C-a [
进入拷贝/回滚模式
其他常用选项:
-c file
使用配置文件file,而不使用默认的$HOME/.screenrc
-d|-D [pid.tty.host]
不开启新的screen会话,而是断开其他正在运行的screen会话
-h num
指定历史回滚缓冲区大小为num行
-list|-ls
列出现有screen会话,格式为pid.tty.host
-d -m
启动一个开始就处于断开模式的会话
-r sessionowner/ [pid.tty.host]
重新连接一个断开的会话。多用户模式下连接到其他用户screen会话需要指定sessionowner,需要setuid-root权限
-S sessionname
创建screen会话时为会话指定一个名字
-v
显示screen版本信息
-wipe [match]
同-list,但删掉那些无法连接的会话