在linux系统中,默认情况下,当关闭ssh终端连接,随之启动的程序也会关闭。
原理分析:
SSH会话关闭时,ssh所关联的pty关闭,系统会给这个pty所关联的session中的所有进程发送SIGHUP信号,SIGHUP的默认信号处理程序是终止进程,除非进程自己处理了
SIGHUP。
那么,有没有办法,实现关闭ssh后,当前执行的进程仍继续运行呢?比如我们用wget命令批量下载上千个远程服务器上的文件时。
解决方法:
使用现成的命令nohup,可以让指定的程序在pty关闭之后继续运行。
运行方法:
现在正常关闭ssh后,服务依然继续运行。
当SecureCRT异常关闭后,后台进程一同关闭的现象罪魁祸首 Signup信号。
症状:使用SecureCRT工具ssh远程连接linux,不退出ssh,而是强行关闭终端(合上笔记本走人)情况下,后台启动的应用也会关闭。
测试案例:
很明显的是关闭终端后,前台运行的程序会被随之关闭,但是后台进程也会因为终端异常关闭而关掉。
一个简单的测试结果:
1、后台执行程序,正常关闭ssh连接,关闭终端的情况:
开启两个终端,其中第一个在后台执行ping操作
在第二个终端观察
tail -f log.txt 可以看到日志一直在写
使用pstree命令可以看到ping的进程存在
Ctrl+D 退出第一个终端 然后关闭终端
第二个终端的日志仍然在写,pstree命令:
看到ping的进程依然存在
2、后台执行程序,非正常关闭ssh连接(模拟突然掉电或者,未来得及退出ssh,或者ssh仍然连接,直接关闭终端SecureCRT)情况:
同样开启两个终端,其中第一个在后台执行ping操作
在第二个终端观察
tail -f log.txt 可以看到日志一直在写
使用pstree命令可以看到ping的进程存在
在不退出ssh的情况下,强行关闭第一个终端(SecureCRT)
在第二个终端观察
tail -f log.txt 可以看到日志已经停止写。
使用pstree命令可以看到ping的进程被停掉
ps aux看不到ping的进程,说明强行关闭终端的情况下后台进程也别kill掉了
查了一下资料,这其中起关键的是 SIGHUP信号
查看所有的信号:
列表中,编号为1 ~ 31的信号为传统UNIX支持的信号,是不可靠信号(非实时的),编号为32 ~ 63的信号是后来扩充的,称做可靠信号(实时信号)。不可靠信号和可靠信号的
区别在于前者不支持排队,可能会造成信号丢失,而后者不会。
SIGHUP信号在用户终端连接(正常或非正常)结束时发出, 通常是在终端的控制进程结束时, 通知同一session内的各个作业, 这时它们与控制终端不再关联。
登录Linux时,系统会分配给登录用户一个终端(Session)。在这个终端运行的所有程序,包括前台进程组和后台进程组,一般都属于这个 Session。
当用户退出Linux登录时,前台进程组和后台有对终端输出的进程将会收到SIGHUP信号。这个信号的默认操作为终止进程,因此前台进程组和后台有终端输出的进程就会中止
。
不过有的程序可以捕获这个信号,并忽略它,这样就算退出了Linux登录,后台程序依旧运行。
此外,对于与终端脱离关系的守护进程,这个信号用于通知它重新读取配置文件。
附,secureCRT异常退出和执行exit的区别?
如果直接关闭secureCRT(此处假设是使用ssh登录终端的),那么对于被登录的系统来说,就是远端程序异常断连。和我们突然断网掉线是一样的效果。
这种情况下,用户并没有信号发送,而是sshd服务检测到对端响应超时,然后向之前建立起的连接以及该连接下(ssh登录后会分配一个bash给用户)的进程发送结束信号。
如果部分进程忽略sshd发送的信号,进程不退出,在分配给用户的bash退出后,该进程将被init进程接管。
对于终端异常退出后,后台进程不关闭问题,有如下的解决办法:
1、使用nohup命令: nohup <command> [argument…] & nohup可以屏蔽SIGHUP信号!
2、使用 screen命令。
简单介绍如下:
需要中断连接:
查询screen进程:
重连