实现ssh关闭后当前进程继续运行的方法

发布时间:2019-10-27编辑:脚本学堂
本文介绍下,当ssh关闭后,仍继续运行当前进程的实现方法。有需要的朋友参考下吧。

linux系统中,默认情况下,当关闭ssh终端连接,随之启动的程序也会关闭。

原理分析:
SSH会话关闭时,ssh所关联的pty关闭,系统会给这个pty所关联的session中的所有进程发送SIGHUP信号,SIGHUP的默认信号处理程序是终止进程,除非进程自己处理了
SIGHUP。

那么,有没有办法,实现关闭ssh后,当前执行的进程仍继续运行呢?比如我们用wget命令批量下载上千个远程服务器上的文件时。

解决方法:
使用现成的命令nohup,可以让指定的程序在pty关闭之后继续运行。

运行方法:
 

复制代码 代码示例:
#nohup program &
 

现在正常关闭ssh后,服务依然继续运行。

当SecureCRT异常关闭后,后台进程一同关闭的现象罪魁祸首 Signup信号。

症状:使用SecureCRT工具ssh远程连接linux,不退出ssh,而是强行关闭终端(合上笔记本走人)情况下,后台启动的应用也会关闭。

测试案例:
很明显的是关闭终端后,前台运行的程序会被随之关闭,但是后台进程也会因为终端异常关闭而关掉。

一个简单的测试结果:
1、后台执行程序,正常关闭ssh连接,关闭终端的情况:
开启两个终端,其中第一个在后台执行ping操作
 

复制代码 代码示例:
ping google.com | tee log.txt &

在第二个终端观察
tail -f log.txt 可以看到日志一直在写
使用pstree命令可以看到ping的进程存在
 

复制代码 代码示例:
|-sshd-+-sshd---sshd---bash---pstree
| `-sshd---sshd---bash-+-ping
| `-tee

Ctrl+D 退出第一个终端 然后关闭终端

第二个终端的日志仍然在写,pstree命令:
 

复制代码 代码示例:
|-ping
ps x
29427 ? S 0:00 ping google.com
 

看到ping的进程依然存在

2、后台执行程序,非正常关闭ssh连接(模拟突然掉电或者,未来得及退出ssh,或者ssh仍然连接,直接关闭终端SecureCRT)情况:
同样开启两个终端,其中第一个在后台执行ping操作
 

复制代码 代码示例:
ping google.com | tee log.txt &

在第二个终端观察
tail -f log.txt 可以看到日志一直在写
使用pstree命令可以看到ping的进程存在
 

复制代码 代码示例:
|-sshd-+-sshd---sshd---bash---pstree
| `-sshd---sshd---bash-+-ping
| `-tee

在不退出ssh的情况下,强行关闭第一个终端(SecureCRT)
在第二个终端观察
tail -f log.txt 可以看到日志已经停止写。
使用pstree命令可以看到ping的进程被停掉
ps aux看不到ping的进程,说明强行关闭终端的情况下后台进程也别kill掉了


查了一下资料,这其中起关键的是 SIGHUP信号
查看所有的信号:
 

复制代码 代码示例:
kill -l
1) SIGHUP 2) SIGINT 3) SIGQUIT 4) SIGILL
5) SIGTRAP 6) SIGABRT 7) SIGBUS 8) SIGFPE
9) SIGKILL 10) SIGUSR1 11) SIGSEGV 12) SIGUSR2
13) SIGPIPE 14) SIGALRM 15) SIGTERM 17) SIGCHLD
18) SIGCONT 19) SIGSTOP 20) SIGTSTP 21) SIGTTIN
22) SIGTTOU 23) SIGURG 24) SIGXCPU 25) SIGXFSZ
26) SIGVTALRM 27) SIGPROF 28) SIGWINCH 29) SIGIO
30) SIGPWR 31) SIGSYS 34) SIGRTMIN 35) SIGRTMIN+1
36) SIGRTMIN+2 37) SIGRTMIN+3 38) SIGRTMIN+4 39) SIGRTMIN+5
40) SIGRTMIN+6 41) SIGRTMIN+7 42) SIGRTMIN+8 43) SIGRTMIN+9
44) SIGRTMIN+10 45) SIGRTMIN+11 46) SIGRTMIN+12 47) SIGRTMIN+13
48) SIGRTMIN+14 49) SIGRTMIN+15 50) SIGRTMAX-14 51) SIGRTMAX-13
52) SIGRTMAX-12 53) SIGRTMAX-11 54) SIGRTMAX-10 55) SIGRTMAX-9
56) SIGRTMAX-8 57) SIGRTMAX-7 58) SIGRTMAX-6 59) SIGRTMAX-5
60) SIGRTMAX-4 61) SIGRTMAX-3 62) SIGRTMAX-2 63) SIGRTMAX-1
64) SIGRTMAX

列表中,编号为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 vi /tmp/2hei.net

需要中断连接:
 

复制代码 代码示例:
screen Ctrl+a d

查询screen进程:
 

复制代码 代码示例:
ps x
20377 ? Ss 0:00 SCREEN vi /tmp/2hei.net

重连

复制代码 代码示例:
screen -r 20377