Linux nohup命令
我们在开发中常需要启动长时间运行的程序,需要在关闭ssh连接时,仍然保持程序正常运行,为此我们需要用到nohup命令。当然也可以使用screen命令,我在之前的文章中已有介绍,可以参考。
nohup命令使用起来并不难,之前我也并没有深入的了解。在最近的开发过程中由于需要启动代理服务,因此使用了nohup命令。但却发现代理服务在关闭ssh连接一段时间之后就会挂掉,因此简单了解了一下nohup,在此记录下。在解决这个问题的过程中,我也尝试使用screen命令,但也没有解决,问题比较奇怪,看现象应该是与代理服务本身以及服务器配置有关。
nohup命令是用来执行其他命令的,同时忽略SIGHUP信号。当我们关闭ssh连接时,操作系统会向正在运行的程序发送SIGHUP信号,通常情况下这个信号会使进程退出,但nohup命令会忽略这个信号。
我们先了解下Linux中的几个概念:
-
进程组:一个或多个进程的集合,每一个进程组有唯一的一个进程组ID,即进程组长进程的ID。
-
会话期:一个或多个进程组的集合,有唯一的一个会话期首进程(session leader)。会话期ID为首进程的ID。
-
会话期可以有一个单独的控制终端(controlling terminal)。与控制终端连接的会话期首进程叫做控制进程(controlling process)。当前与终端交互的进程称为前台进程组,其余进程组称为后台进程组。
根据POSIX.1定义:
-
挂断信号(SIGHUP)默认的动作是终止程序。
-
当终端接口检测到网络连接断开,将挂断信号发送给控制进程(会话期首进程)。
-
如果会话期首进程终止,则该信号发送到该会话期前台进程组。
-
一个进程退出导致一个孤儿进程组产生时,如果任意一个孤儿进程组进程处于STOP状态,发送SIGHUP和SIGCONT信号到该进程组中所有进程。
因此当网络断开或终端窗口关闭后,也就是ssh连接断开以后,控制进程收到SIGHUP信号退出,会导致该会话期内其他进程退出。
使用后台运行命令“&”并没有摆脱ssh进程组控制,只是把进程放入了后台进程组。在关闭ssh连接时,同样会退出程序。
之前我们介绍了screen命令,这里把nohup命令和screen命令做一下对比:
-
nohup命令只保证单个指定进程不退出,screen命令会保留整个会话期内的所有进程;
-
nohup命令相对简单,对于复杂的人机交互还是需要screen命令;
-
nohup命令执行的程序只能通过kill命令来杀死,而screen命令可以更友好些;
-
screen命令可以保留会话的环境设置,通过恢复会话,可以实现工作环境的快速切换;
-
相对而言nohup占用资源更少,没有交互需求的时候,nohup就能满足需要了;
screen是可以完全替代nohup的。从个人偏好来说,也更喜欢screen,方便且强大:)