场景:ssh 登录远程 Linux 服务器后运行一些耗时较长的任务,中途由于网络不稳定导致ssh断开,任务执行失败。
原因:当网络断开或终端窗口关闭后,控制进程收到SIGHUP信号退出,导致该会话期内其他进程退出。
通过pstree命令可以查看进程间的树状结构,只要父进程是bash,如果ssh断了,ssh就会向所有子进程发送SIGTERM信号,然后所有子进程退出。
下面通过一些方法可以让命令提交后不受本地关闭终端窗口、网络断开连接的干扰。
nohup
nohup就是让提交的命令忽略 hangup 信号。nohup 的使用是十分方便的,只需在要处理的命令前加上 nohup 即可,标准输出和标准错误缺省会被重定向到 nohup.out 文件中。一般我们可在结尾加上”&”来将命令同时放入后台运行,也可用”>filename 2>&1″来更改缺省的重定向文件名。
nohup ping www.baidu.com >test.out 2>&1 &
nohup ./script.sh >/dev/null 2>&1 &
disown / Ctrl-z
如果我们未加任何处理就直接运行了命令,而该命令又需要运行很长一段时间,这时想加 nohup 已经为时已晚,只能通过作业调度和 disown 来解决这个问题了。
shell>cp -r testLargeFile largeFile #提交命令时未使用“&”将命令放入后台运行
[1]+ Stopped cp -i -r testLargeFile largeFile2
#####这时可使用 CTRL-z 将当前进程挂起到后台暂停运行######
shell>bg %1 #将其放入后台运行
[1]+ cp -i -r testLargeFile largeFile2 &
#可通过fg %1来将挂起的进程重新放回前台
shell>jobs #查看作业列表
[1]+ Running cp -i -r testLargeFile largeFile2 &
shell>disown -h %1 ##忽略HUP信号,当使用过 disown 之后,会将把目标作业从作业列表中移除,我们将不能再使用jobs来查看它,但是依然能够用ps -ef查找到它。
###disown -h jobspec来使某个作业忽略HUP信号。
###disown -ah 来使所有的作业都忽略HUP信号。
###disown -rh 来使正在运行的作业忽略HUP信号。
shell>ps -ef |grep largeFile2
root 5790 5577 1 10:04 pts/3 00:00:00 cp -i -r testLargeFile largeFile2
root 5824 5577 0 10:05 pts/3 00:00:00 grep largeFile2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
shell>cp-rtestLargeFilelargeFile#提交命令时未使用“&”将命令放入后台运行
[1]+Stoppedcp-i-rtestLargeFilelargeFile2
#####这时可使用 CTRL-z 将当前进程挂起到后台暂停运行######
shell>bg%1#将其放入后台运行
[1]+cp-i-rtestLargeFilelargeFile2&
#可通过fg %1来将挂起的进程重新放回前台
shell>jobs#查看作业列表
[1]+Runningcp-i-rtestLargeFilelargeFile2&
shell>disown-h%1##忽略HUP信号,当使用过 disown 之后,会将把目标作业从作业列表中移除,我们将不能再使用jobs来查看它,但是依然能够用ps -ef查找到它。
###disown -h jobspec来使某个作业忽略HUP信号。
###disown -ah 来使所有的作业都忽略HUP信号。
###disown -rh 来使正在运行的作业忽略HUP信号。
shell>ps-ef|greplargeFile2
root57905577110:04pts/300:00:00cp-i-rtestLargeFilelargeFile2
root58245577010:05pts/300:00:00greplargeFile2
screen
Screen是一款由GNU计划开发的用于命令行终端切换的自由软件。用户可以通过该软件同时连接多个本地或远程的命令行会话,并在其间自由切换。GNU Screen可以看作是窗口管理器的命令行界面版本。它提供了统一的管理多个会话的界面和相应的功能。
未使用 screen 时我们所处的 bash 是 sshd 的子进程,当 ssh 断开连接时,HUP 信号自然会影响到它下面的所有子进程。而使用 screen 后就不同了,此时 bash 是 screen 的子进程,而 screen 是 init(PID为1)的子进程。那么当 ssh 断开连接时,HUP 信号自然不会影响到 screen 下面的子进程了。
语法: # screen [-AmRvx -ls -wipe][-d ][-h ][-r ][-s ][-S ]
选项:
-A 将所有的视窗都调整为目前终端机的大小。
-d 将指定的screen作业离线。
-h 指定视窗的缓冲区行数。
-m 即使目前已在作业中的screen作业,仍强制建立新的screen作业。
-r 恢复离线的screen作业。
-R 先试图恢复离线的作业。若找不到离线的作业,即建立新的screen作业。
-s 指定建立新视窗时,所要执行的shell。
-S 指定screen作业的名称。
-v 显示版本信息。
-x 恢复之前离线的screen作业。
-ls或-list 显示目前所有的screen作业。
-wipe 检查目前所有的screen作业,并删除已经无法使用的screen作业。
常用命令:
用screen -S SessionName 建立一个新的会话。
用快捷键CTRL-a d 来暂时断开当前会话。
用screen -list 来列出所有会话。
用screen -r SessionName来重新连接指定会话。
用快捷键CTRL-a k 来杀死当前会话。
用screen -wipe命令清除该会话。
shell>screen -S session1 #新建一个screen会话
shell>ping www.baidu.com #screen会话内执行命令
###Ctrl-a d #暂时断开(detach)screen会话
shell>screen -ls #查看会话列表
There is a screen on:
19003.session(Detached)
1 Socket in /var/run/screen/S-zjdc.
shell>screen -r session1 #重新连接到session1会话
###Ctrl-a k #关闭会话
1
2
3
4
5
6
7
8
9
10
11
12
13
14
shell>screen-Ssession1#新建一个screen会话
shell>pingwww.baidu.com#screen会话内执行命令
###Ctrl-a d #暂时断开(detach)screen会话
shell>screen-ls#查看会话列表
Thereisascreenon:
19003.session(Detached)
1Socketin/var/run/screen/S-zjdc.
shell>screen-rsession1#重新连接到session1会话
###Ctrl-a k #关闭会话
Supervisor
Supervisord是用Python实现的一款非常实用的进程管理工具。supervisord会帮你把管理的应用程序转成daemon程序,而且可以方便的通过命令开启、关闭、重启等操作,而且它管理的进程一旦崩溃会自动重启,这样就可以保证程序执行中断后的情况下有自我修复的功能。
安装:
CentOS安装:yum -y install supervisord
Ubuntu安装:apt-get install supervisor
安装好以后,有两个可执行文件和一个配置文件(平台差异,可能路径不一致)
/usr/bin/supervisord 服务守护进程。
/usr/bin/supervisorctl 服务控制程序,比如:status/start/stop/restart process等。
/etc/supervisor/supervisord.conf 配置文件,定义服务名称以及接口等。
配置:
正常情况下我们并不对/etc/supervisor/supervisord.conf作出任何的改动,而是在/etc/supervisor/conf.d/下面添加一个新的 *.conf 文件,比如count_supervisor.conf,加入如下片段:
shell>vim /etc/supervisor/conf.d/count_supervisor.conf
[program:count] #program后面跟服务的名称
command=/root/count.sh #command是程序的执行路径
autorestart=true #autorestart是表示自动启动
stdout_logfile=/var/log/supervisor/count.log #stdout_logfile是捕获标准输出
1
2
3
4
5
shell>vim/etc/supervisor/conf.d/count_supervisor.conf
[program:count]#program后面跟服务的名称
command=/root/count.sh#command是程序的执行路径
autorestart=true#autorestart是表示自动启动
stdout_logfile=/var/log/supervisor/count.log#stdout_logfile是捕获标准输出
启动:
shell>service supervisord start ##启动supervisord服务
shell>supervisorctl status count ##获取count服务的状态
RUNNING pid 29663, uptime 0:02:46
shell>kill -9 29663 ##杀掉count进程
shell>supervisorctl status count ##再次获取count服务的状态,发现pid有变。因为是autorestart,这里又自动启动了count。
RUNNING pid 29897, uptime 0:00:02
shell>supervisorctl stop count ##停止count服务
shell>supervisorctl stop count ##再次停止服务,会有错误信息count:ERROR(notrunning)
shell>supervisorctl start count ##启动count服务count:started
shell>supervisorctl stop all ##停止全部进程,注:start、restart、stop都不会载入最新的配置文件
shell>supervisorctl reload ##载入最新的配置文件,并按新的配置启动、管理所有进程
1
2
3
4
5
6
7
8
9
10
11
shell>servicesupervisordstart##启动supervisord服务
shell>supervisorctlstatuscount##获取count服务的状态
RUNNINGpid29663,uptime0:02:46
shell>kill-929663##杀掉count进程
shell>supervisorctlstatuscount##再次获取count服务的状态,发现pid有变。因为是autorestart,这里又自动启动了count。
RUNNINGpid29897,uptime0:00:02
shell>supervisorctlstopcount##停止count服务
shell>supervisorctlstopcount##再次停止服务,会有错误信息count:ERROR(notrunning)
shell>supervisorctlstartcount##启动count服务count:started
shell>supervisorctlstopall##停止全部进程,注:start、restart、stop都不会载入最新的配置文件
shell>supervisorctlreload##载入最新的配置文件,并按新的配置启动、管理所有进程
Web界面查看
shell>vim /etc/supervisor/supervisord.conf
http_port=10.3.3.3:9001 ##默认9001端口
##默认无密码,去掉分号可以设置账号和密码
;http_username=user
;http_password=123
1
2
3
4
5
6
shell>vim/etc/supervisor/supervisord.conf
http_port=10.3.3.3:9001##默认9001端口
##默认无密码,去掉分号可以设置账号和密码
;http_username=user
;http_password=123
重启supervisor服务后,打开浏览器输入:http://10.3.3.3:9001即可。