linux中运行耗时的程序

声明:
本blog欢迎转发,但请保留原作者信息:
新浪微博:@孔令贤HW
Blog地址:http://blog.csdn.net/lynn_kong
内容系本人学习、研究和总结,如有雷同,实属荣幸!


前几天微博中有人讲到要在linux中运行耗时的程序时,在断开SSH或网络中断时,如何保护程序不受影响(比如大文件的拷贝不中断):


因为自己以前使用过screen,但没有使用过nohup和setid,于是借此机会,学习一下,顺便做个记录,便于以后翻看。

1. 前言

首先有一个问题就是,我们平常使用ssh登录服务器运行一个耗时程序,程序未运行完,我们断开ssh,此时程序也会中断。这是因为进程收到了SIGHUP信号而退出。举个例子:
1. 打开两个ssh终端窗口,在其中一个运行top命令,在另一个窗口可以查看:

2. 关闭第一个SSH窗口,在另一个窗口中可以看到top也被杀掉了。


那么如何可以解决这个问题?有两种途径:要么让进程忽略 HUP 信号,要么让进程运行在新的会话里从而成为不属于此终端的子进程。

2. nohup/setsid

对于单个命令的长时间运行,可以使用如下两种方法:

2.1 nohup

nohup 的用途就是让提交的命令忽略HUG信号。nohup使用非常简单,如果程序的标准输出/标准错误是终端,nohup默认将其重定向到nohup.out文件。值得注意的是nohup命令只是使程序忽略SIGHUP信号,一般我们可在结尾加上"&"来将命令同时放入后台运行。例如:
root@openstack:~# nohup ping www.baidu.com &
[1] 20532
root@openstack:~# nohup: ignoring input and appending output to `nohup.out'
可以把当前窗口关闭,新开一个终端窗口,运行如下命令查看:
root@openstack:~# ps -ef | grep ping 
root     20532 13977  0 00:56 pts/0    00:00:00 ping www.baidu.com
root     22449 20000  0 00:57 pts/1    00:00:00 grep --color=auto ping
可以看到,程序依然在运行。

2.2 setid

nohup 无疑能通过忽略 HUP 信号来使进程避免中途被中断,但如果一个进程不属于接受 HUP 信号的终端的子进程,那么自然也就不会受到 HUP 信号的影响,此时就可以使用setid达到同样的目的。setid的使用与nohup相似,只需在要处理的命令前加上 setsid 即可,但这里需要指出的是,setid运行的进程的父进程是init(PPID=1),而不是当前终端的进程 ID.

3. disown

前面已经讲了在命令前加上 nohup 或者 setsid 就可以避免 HUP 信号的影响,但如果程序已经执行,而忘了加nohup或setid,该如何补救才能让它避免 HUP 信号的影响呢?
root@openstack:~# ping www.baidu.com >temp.txt &
[1] 20154
root@openstack:~# jobs
[1]+  Running                 ping www.baidu.com > temp.txt &
root@openstack:~# disown -h %1
root@openstack:~# ps -ef | grep ping
root     20154 14260  0 01:14 pts/0    00:00:00 ping www.baidu.com
root     21336 14260  0 01:14 pts/0    00:00:00 grep --color=auto ping
root@openstack:~# logout
(上面的ping命令在我的ubuntu虚拟机上貌似不受HUP信号的影响,因此上述的命令仅仅是为了演示)
如果不是后台运行的命令,则可以先ctrl+z将程序暂停,然后bg命令使其在后台运行,之后操作与上述一样。

4. screen

sceen我想大家基本上都用过,就不细讲了,只举例说明。
1. 打开一个终端窗口。输入screen新建会话(也可以screen –S name指定会话的名称,便于识别)
root@openstack:~# screen -S kong
之后就会进入一个全新的shell窗口。
2. 可以ctrl+a,A为窗口命名(注意,这里是命名窗口,而不是整个session),这里我命名为"window1"

3. 在"window1"中,ctrl+a,c,再新建一个窗口
4. ctrl+a,A, 将新建的窗口命名为"window2"
5. ctrl+a,w,显示"kong"会话中的所有窗口

6. ctrl+a,0,切换到"window1",这里也可以使用ctrl+a,n或ctrl+a,p来进行上下切换。
7. 在"window1"中执行ping www.baidu.com命令
root@openstack:~# ping www.baidu.com
PING www.a.shifen.com (119.75.217.56) 56(84) bytes of data.
64 bytes from 119.75.217.56: icmp_req=1 ttl=128 time=29.5 ms
64 bytes from 119.75.217.56: icmp_req=2 ttl=128 time=23.4 ms
64 bytes from 119.75.217.56: icmp_req=3 ttl=128 time=23.5 ms
……
8. ctrl+a,1,切换到"window2",随意做一些操作。然后ctrl+a,0切换到"window1",ping命令仍在执行。
9. 关闭xshell,重新打开,登录服务器。键入screen -ls可以查看到所有的screen会话。
root@openstack:~# screen -ls
There is a screen on:
7166.kong (2013年05月05日 01时29分08秒) (Detached)
1 Socket in /var/run/screen/S-root.
10. screen -r 7166,进入会话,会发现重新进入了之前退出时的界面。有时候当你挂起screen,下次想连的时候,有时候会出现screen session的状态为Attached而怎么连也连不上的情况,此时可用“screen -D -r <session-id>”先踢掉前一用户,再登陆
11. ctrl+a,d,保留程序执行状态,断开当前的会话,此时键入screen -ls与前面看到的输出一样。
12. 在一个screen窗口中键入exit或ctrl+a,k,会退出当前窗口,如果会话中只有一个窗口,那么会退出整个screen会话。
13. 如果要重命名session,ctrl+a+: 然后输入sessionname <新名字>

这里简单解释一下为什么使用screen不会中断程序的执行,screen 是 init(PID为1)的子进程。那么当 ssh 断开连接时,HUP 信号自然不会影响到 screen 下面的子进程了。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值