Linux关闭终端(或者关闭SSH等)后运行的程序自动停止

问题描述:

之前在服务器上起一个python的服务,放到后台运行。 python pyserver.py &.  当我关闭这个SSH之后,该服务不可用,再次登入到服务器,已经没有这个python进程啦。

问题定位:

通过上面问题的表象,可以发现是跟SSH关闭有关。为什么ssh关闭,会导致正在运行的程序死掉。通过查看相关的资料,发现真正的元凶是SIGHUP信号导致的。

在linux中,有下面几个概念:

进程组: 一个或多个进程的集合,每一个进程组都有唯一一个进程组ID,即进程组
会话器: 一个或多个进程组的集合,有唯一一个会话期首进程(session leader)。会话期ID为首进程的ID。
控制进程: 与控制终端连接的会话期首进程叫做控制进程.
当前与终端交互的进程称为前台进程组。其余进程组称为后台进程组。

一般缩写:

  • PID = 进程ID (由内核根据延迟重用算法生成)
  • PPID = 父进程ID(只能由内核修改)
  • PGID = 进程组ID(子进程、父进程都能修改)
  • SID = 会话ID(进程自身可以修改,但有限制,详见下文)
  • TPGID= 控制终端进程组ID(由控制终端修改,用于指示当前前台进程组)

会话和进程组的关系:

每次用户登录终端时会产生一个会话(session)。从用户登录开始到用户退出为止,这段时间内在该终端执行的进程都属于这一个会话。

每个进程除了有一进程ID之外,还属于一个进程组(Process Group)。进程组是一个或多个进程的集合,每个进程组有一个唯一的进程组ID。多个进程属于进程组的情况是多个进程用管道“|”号连接进行执行。如果在命令行执行单个进程时这个进程组只有这一个进程。

挂断信号(SIGHUP)默认的动作是终止程序。

当终端接口检测到网络连接断开,将挂断信号发送给控制进程(会话期首进程)。如果会话期首进程终止,则该信号发送到该会话期前台进程组。一个进程退出导致一个孤儿进程组中产生时,如果任意一个孤儿进程组进程处于STOP状态,发送SIGHUP和SIGCONT信号到该进程组中所有进程。

因此当网络断开或终端窗口关闭后,也就是SSH断开以后,控制进程收到SIGHUP信号退出,会导致该会话期内其他进程退出。

解决的办法

nohup命令:

如果你正在运行一个进程,而且你觉得在退出帐户时该进程还不会结束,那么可以使用nohup命令。该命令可以在你退出帐户/关闭终端之后继续运行相应的进程。nohup就是不挂起的意思。

我们现在开始启动服务 python pyserver.py,并且希望在后台运行.我们就可以使用nohup,命令如下:

nohup python pyserver.py &

此时默认地程序运行的输出信息放到当前文件夹的nohup.out 文件中去,加不加&并不会影响这个命令。只是让程序前台或者后台运行而已。

nohup命令说明:
用途:不挂断地运行命令。
语法:nohup Command [ Arg ... ] [ & ]
描述:nohup 命令运行由 Command 参数和任何相关的 Arg 参数指定的命令,忽略所有挂断(SIGHUP)信号。在注销后使用 nohup 命令运行后台中的程序。要运行后台中的 nohup 命令,添加 & ( 表示“and”的符号)到命令的尾部。

无论是否将 nohup 命令的输出重定向到终端,输出都将附加到当前目录的 nohup.out 文件中。如果当前目录的 nohup.out 文件不可写,输出重定向到 $HOME/nohup.out 文件中。如果没有文件能创建或打开以用于追加,那么 Command 参数指定的命令不可调用。如果标准错误是一个终端,那么把指定的命令写给标准错误的所有输出作为标准输出重定向到相同的文件描述符。

退出状态:该命令返回下列出口值:

  • 126 可以查找但不能调用 Command 参数指定的命令。
  • 127 nohup 命令发生错误或不能查找由 Command 参数指定的命令。

否则,nohup 命令的退出状态是 Command 参数指定命令的退出状态。

使用 jobs 查看任务,使用 fg %n关闭。

延伸:

为什么守护程序就算ssh 打开的,就算关闭ssh也不会影响其运行?

因为他们的程序特殊,比如httpd –k start运行这个以后,他不属于sshd这个进程组  而是单独的进程组,所以就算关闭了ssh,和他也没有任何关系!

[[email protected] ~]# pstree |grep http
|-httpd
[[email protected] ~]# pstree |grep top
|-sshd-+-sshd—bash—top

守护进程的启动命令本身就是特殊的,和一般命令不同的,比如mysqld_safe 这样的命令 一旦使用了  就是守护进程运行。所以想把一般程序改造为守护程序是不可能。

时间: 2024-12-31 04:05:16

Linux关闭终端(或者关闭SSH等)后运行的程序自动停止的相关文章

Qt Creator新安装后运行一个程序后,出现错误:Error while building/deploying project dict-qt (kit: Desktop Qt 5.10.0 MinGW 32bit) When executing step "qmake"

1.环境介绍:在windows10 Pro下,当前Qt Creator版本,如下图所示: 2.问题描述:当用Qt Creator新建一个工程后,按Ctrl + R 构建/部署时,出现问题,问题截图如下: 3.解决方案:这是由于Qt Creator打开的工程文件夹的绝对路径中存在中文字符,只需将工程文件夹复制到英文文件目录下打开,即可编译运行成功! 或者关闭Qt Creator后,将中文路径改为英文路径再打开Qt Creator,也可编译运行成功! 4.小结:Qt Creator的工程文件夹的绝对

Linux前台的程序转到后台执行(关闭终端而不杀死命令)

你是否经常遇到这样的情况,通过SSH或者终端putty连接到一台linux/unix机器,执行一个程序.一个脚本或者一条命令,但现在你需要关闭SSH或者终端,由于该该程序.脚本或者命令正在运行,一旦你直接关闭而不做任何处理这个进程就会一起关闭,做到一半的工作就这样浪费掉,实在是可惜! 下面介绍一种方法可以在需要关闭终端的时,让正在运行的程序.脚本或命令转到后台执行,假设你的程序.脚本或者命令正在执行,下面可进行这样操作: 1.按下ctrl+z2.输入命令bg3.输入disown (在输入时可能只

解决Linux关闭SSH,终端后运行程序终止问题(包括后台)

问题描述: 每次SSH到服务器上,然后运行了一个自己写的服务端程序,比如 ./myserver.sh ,然后关闭ssh或者终端之后,发现服务不能访问. 简要分析下: 根据   这篇博文  的提示,ssh登录后会新建一个会话,一个登陆shell发起的会话,一般由一个会话首进程.一个前台进程组.一个后台进程组组成.通常来说,会话首进程是一个登录shell,比如bash.进程组是一个或多个进程的集合,进程组属于一个会话.一般来说,一个进程组中的其它进程的父进程是进程组组长进程的ID,如果,这个进程组组

让命令提交后不受本地关闭终端窗口/网络断开连接的干扰

项目中操作场景:本地机器上通过ssh连接服务器进行相关操作.这里就出现一个问题,在我们本地程序中,向服务器发送一个命令是没有任何问题的,可是当本次程序意外关闭或者由于网络断开连接,这是我们通过本地程序在服务器上创建的进程也就会被杀死.所以问题就来了:如何让对应进程能无间断的执行,即通过本机程序在服务器上创建一个进程,当本地关闭ssh连接或者与服务器的网络断开之后,这个创建的进程要继续存在而不会被杀死.在IBM 上看到一遍文章,对这个问题的解决方法讲解的很详细,现在简要介绍下: 我们知道,当用户注

Linux使用screen实现关闭ssh连接的情况下,让程序继续在后台运行

Ubuntu默认没有安装screen,需要手动安装. 安装命令: sudo apt-get install screen 简单的操作方法: 直接输入命令 screen 进入screen子界面,此时putty标题栏会指示处于子界面状态,然后运行你的程序 操作命令... 然后按下Ctrl+A后抬起,然后按下d键,此时切换回主界面,Putty的窗口标题栏也会指示. 此时就是断开ssh(直接关闭putty的窗口),程序仍在运行. 以后重新ssh连接后,如果要找回之前的窗口,输入 screen -ls 查

[Linux]在终端启动程序关闭终端不退出的方法

?? 在终端启动程序关闭终端不退出的方法 普通情况下关闭终端时,那么在这个终端中启动的后台程序也会终止.要使终端关闭后,后台程序保持运行,使用这个指令: nohup 命令 & 如:nohup test.sh &

解决linux下source /etc/profile关闭终端失效问题

本来想配置环境变量的,看网上和博客上很多说改/etc/profile,然后source /etc/profile之后就可以永久保存使环境变量生效,但是终端一关闭,就环境变量就失效了,其他终端也用不了.网上有说在当前用户目录下创建.bash_profile文件,编写环境变量,然后执行命令source ~/.bash_profile之后就能使这个用户永久生效.但是还是和之前/etc/profile一样,失效了. 解决办法: 在~/.bashrc文件里改环境配置,sourct ~/.bashrc,最后

一起talk C栗子吧(第一百七十回:C语言实例--关闭终端中的回显功能一)

各位看官们,大家好,上一回中咱们说的是再谈内置宏的例子,这一回咱们说的例子是:关闭终端中的回显功能 .闲话休提,言归正转.让我们一起talk C栗子吧! 看官们,我们今天介绍的是关闭终端中的回显功能,首先介绍一下什么是回显功能.当我们在终端中输入字符时终端马上就会显示我们输入的字符,这就是回显功能.我想这样的操作,大家已经司空见惯了,只是不知道它还有一个专业的名字:回显. 回显给我们带来了很多方便,比如我们可以及时看到自己输入到终端中的内容,而且当输入的内容有错误时还可以进行修改.这时有看官说:

一起talk C栗子吧(第一百七十四回:C语言实例--关闭终端中的缓冲功能二)

各位看官们,大家好,上一回中咱们说的是关闭终端中缓冲功能的例子,这一回咱们继续说该例子.闲话休提,言归正转.让我们一起talk C栗子吧! 看官们, 我们在上一回中介绍了如何关闭终端中的缓冲功能,当时是借助系统命令stty实现该功能的,这一回中我们将介绍另外一种关闭终端中回显功能的方法.该方法是通过终端的termios编程接口来操作终端的.关于termios接口的介绍和编程接口,我们在一百七十一回中介绍过了,因此,我们直接介绍如何通过termios编程接口来关闭终端缓冲功能. 下面是详细的操作步