linux断开会话不中断进程,Linux让进程后台运行且连接断开不影响(nohup、setsid、disown、screen)...
背景
由于Linux的某些特性,例如可以多用户同时登陆、服务器运用广泛等,我们通常会用ssh去连接一台远程的Linux主机,或者在开发机上(本机)开多个terminal。而在我们运行一个耗时较长的任务时,如果因为网络原因,或其他未知异常导致终端连接断开,那我们的任务随即也会被kill掉。这是因为当你连接断开的时候,终端会收到一个SIGHUP信号,进而终端当前进程下的所有子进程,所以与之相关的任务将全被kill。而我们很多情况下想要的是在意外发生的时候,任务继续跑而不受父进程的影响。
元凶:SIGHUP 信号
让我们来看看为什么关掉窗口/断开连接会使得正在运行的程序死掉。
在Linux/Unix中,有这样几个概念:
进程组(process group):一个或多个进程的集合,每一个进程组有唯一一个进程组ID,即进程组长进程的ID。
会话期(session):一个或多个进程组的集合,有唯一一个会话期首进程(session leader)。会话期ID为首进程的ID。
会话期可以有一个单独的控制终端(controlling terminal)。与控制终端连接的会话期首进程叫做控制进程(controlling process)。当前与终端交互的进程称为前台进程组。其余进程组称为后台进程组。
根据POSIX.1定义:
挂断信号(SIGHUP)默认的动作是终止程序。
当终端接口检测到网络连接断开,将挂断信号发送给控制进程(会话期首进程)。
如果会话期首进程终止,则该信号发送到该会话期前台进程组。
一个进程退出导致一个孤儿进程组中产生时,如果任意一个孤儿进程组进程处于STOP状态,发送SIGHUP和SIGCONT信号到该进程组中所有进程。
因此当网络断开或终端窗口关闭后,控制进程收到SIGHUP信号退出,会导致该会话期内其他进程退出。
解决方案
未雨绸缪派
nohup
通过背景分析,我们很容易想到,如果捂住终端的眼睛(让终端忽略SIGHUP信号),是不是就不会干掉子进程了?nohup就是干这样一件事情,其用法也很简单,命令前加上nohup即可:
nohup command &
示例:
➜ ~ nohup python -m SimpleHTTPServer 8421 &
[1] 7533
appending output to nohup.out
➜ ~ ps -ef | grep 7533
501 7533 6838 0 9:39AM ttys003 0:00.06 python -m SimpleHTTPServer 8421
501 7613 6838 0 9:39AM ttys003 0:00.00 grep --color=auto --exclude-dir=.bzr --exclude-dir=CVS --exclude-dir=.git --exclude-dir=.hg --exclude-dir=.svn 7533
➜ ~ ls -al nohup.out
-rw------- 1 vien staff 0 Aug 30 09:39 nohup.out
说明:
1.后缀&是让其后台运行,但注意,后台运行不代表不受SIGHUP信号影响,连接断开的话依然会终止任务。
2.我们可以看到下面的appending output to nohup.out,然后在最后我列出了这个文件,可以看到就是刚刚创建的。任务所有的输出都将输出到这个文件中,当然也可以自定输出路径、文件名、内容等。
3.然后中间我列出了这个进程,可以观察到,其父进程ID与当前窗口下的进程ID是相同的6838 ,也就是说这个任务还是隶属于当前进程,这将与下面的方法有所不同。
重定向输出位置:nohup command > vienout.log 2>&1 &
由于使用nohup时,会自动将输出写入nohup.out文件中,如果文件很大的话,nohup.out就会不停的增大,我们可以利用Linux下一个特殊的文件/dev/null来解决这个问题,这个文件就相当于一个黑洞,任何输出到这个文件的东西都将消失
只保留输出错误信息 nohup command >/dev/null 2>err.log &
所有信息都不要 nohup command >/dev/null 2>&1 &
这里解释一下后面的2>&1 。 这涉及到Linux的重定向,其中0、1、2分别是标准输入、标准输出、标准错误输出,用来指定需要重定向的标准输入输出。默认情况下是标出输出,也就是1 。例如我们而上文提到的 2>&1 是 将错误信息重定向到标准输出。
setsid
上面讲的忽略SIGHUP信号,那如果我们给它(任务)换个爹(父进程)呢?这时候我们就可以用到setsid ,用户与上一个一样简单:
setsid command
示例:
➜ ~ setsid ping google.com
...(省略输出)
➜ ~ ps -ef | grep ping
moma 6186 1 0 09:55 ? 00:00:00 ping google.com
moma 8681 7988 0 09:59 pts/37 00:00:00 grep --color=auto --exclude-dir=.bzr --exclude-dir=CVS --exclude-dir=.git --exclude-dir=.hg --exclude-dir=.svn ping
说明:
1.我们可以看到这里任务的父进程ID变成了1,也就是init进程,这样它爹就不会轻易挂掉了。
2.之所以省略了若干输出,是因为输出太多了,没有重定向导入/dev/null或者别的地方,可想而知,人家亲爹不要,换个了有钱的干爹,你再骂他说:“你个龟儿子,不听老子话,就不给你零花钱”,当然不会鸟你了,也就是你的Ctrl+C之类的命令都是不可用的,你签字(回车)的那一刻,这儿子就归别人了。
说明:setsid命令在Mac系统下是不存在的
() + &
江湖中传闻一个关于 subshell 的小技巧。我们知道,将一个或多个命名包含在“()”中就能让这些命令在子 shell 中运行中,从而扩展出很多有趣的功能。
当我们将"&"也放入“()”内之后,我们就会发现所提交的作业并不在作业列表中,也就是说,是无法通过jobs来查看的。
(ping command &)
这里就不做示例,通过上面两个例子这个很容易就是用了。而且这个基本跟第二个一样,也是换爹。
亡羊补牢派
刚刚讲的那些都是任务开始前搞事情,那么万一我们脑子一抽,手一抖,没有任何安全措施就一下子回了车呢?莫慌,还有这种操作。
disown
使某个作业忽略SIGHUP信号
disown jobspec
示例:
➜ ~ python -m SimpleHTTPServer 8877 &
[1] 20815
➜ ~ Serving HTTP on 0.0.0.0 port 8877 ...
➜ ~ jobs
[1] + running python -m SimpleHTTPServer 8877
➜ ~ disown %1
➜ ~ jobs
➜ ~
可以看到进程ID 20815前面有一个数字,加一个%即可
说明:这个命令是对作业(job)的操作,所以呢,首先你得把它变成job,很简单,如果你在运行前命令后面加了& 那恭喜你,现在他就是一个job,如果没有呢,也不要急,按下Ctrl+z 就可以把它挂到后台,成为一个job,此时我们可以通过jobs命令来查看所有的job。
关于job还有一些操作,bg %n是将job后台运行,fg %n是将job拿到前台运行,kill %n是杀掉这个job
需要注意的是,当使用过 disown 之后,会将把目标作业从作业列表中移除,我们将不能再使用jobs来查看它,但是依然能够用ps -ef查找到它。
不知道什么反正很吊派
screen 提供了 ANSI/VT100 的终端模拟器,使它能够在一个真实终端下运行多个全屏的伪终端。
screen
建立一个新session
screen
列出所有session
screen -ls
重新连接指定session
screen -r screen_pid
用快捷键CTRL + ad 来暂时断开当前session,CTRL + d 结束当前session。
示例:
➜ ~ screen
(此时跳转到新窗口,按Ctrl+ad暂时断开)
➜ ~ screen -ls
There is a screen on:
31665.pts-37.MBP (2017年08月30日 10时59分49秒) (Attached)
1 Socket in /var/run/screen/S-moma.
➜ ~ screen -r 31665
(恢复到screen_pid为31665的session)
➜ ~ ping google.com &
[1] 2184
(Ctrl+ad离开此session,然后查看进程树)
➜ ~ pstree -H 2184
systemd─┬─ModemManager─┬─{gdbus}
│ └─{gmain}
├─NetworkManager─┬─dhclient
│ ├─dnsmasq
│ ├─{gdbus}
...
├─rtkit-daemon───2*[{rtkit-daemon}]
├─screen───zsh───ping
├─sshd───sshd───sshd───zsh─┬─pstree
│ └─3*[python]
├─2*[systemd───(sd-pam)]
...
(此时我们再连接回刚刚的session可以看到还是在运行的)
说明:
1.通过上面的进程树,我们可以很容易观察到,screen───zsh───ping是直接挂在systemd下的,这也就是不会受SIGHUP信号影响的原因,这跟setsid的原理是一样的,前文提到是init进程实在Linux下的,当前是systemd是因为在实在Mac系统下操作的。
2.还有就是这个命令如果机器上没有的话需要安装,Ubuntu的话是sudo apt-get install screen
3.这个命令是十分强大的,这里只是简单介绍,还有很多神奇的操作,想要玩爽还得自己用man screen去看
参考和引用:
Linux 后台运行
我们常常会用终端连接Linux服务器,然后在运行类似Tomcat 、Web Logic等 web容器的时候希望退出终端依然可以运行。
我们可以通过 nohup command & 来使程序后台运
以Tomcat为例nohup ./startup.sh &
然后在shell中提示了nohup成功后:
nohup: ignoring input and appending output to ‘nohup.out’
然后按键盘任意键,回到shell输入命令窗口,然后在shell中输入
exit
退出终端,这时候,你的Tomcat就作为后台服务挂在Linux上了。
注意:不要执行完nohup直接点击关闭程序关闭终端,这样会干掉该命令的session,导致nohup对应的进程被通知一起被干掉,从而导致后台运行失败。
上文提到过nohup成功后的提示:nohup: ignoring input and appending output to ‘nohup.out’
默认情况下nohup的作业的所有输出会被重定向到 nohup.out这个文件中,当然,你也可以指定输出:
nohup command > vienout.txt 2>&1 &
由于使用nohup时,会自动将输出写入nohup.out文件中,如果文件很大的话,nohup.out就会不停的增大,我们可以利用Linux下一个特殊的文件/dev/null来解决这个问题,这个文件就相当于一个黑洞,任何输出到这个文件的东西都将消失
只保留输出错误信息 nohup command >/dev/null 2>log &
所有信息都不要 nohup command >/dev/null 2>&1 &
这里解释一下后面的2>&1 。 这涉及到Linux的重定向,其中0、1、2分别是标准输入、标准输出、标准错误输出,用来指定需要重定向的标准输入输出。默认情况下是标出输出,也就是1 。例如我们而上文提到的 2>&1 是 将错误信息重定向到标准输出。
还有就是如果不想让程序输出,Linux下有一个/dev/null的特殊文件,就像一个黑洞,所有输出到这个文件的信息全部会消失,如果你不需要输出日志,这样做就不会导致输出日志文件越来越大,占用存储空间的问题了
关于Linux,新手想继续了解一些知识的话,推荐看一下《鸟哥的Linux私房菜》,讲的简单易懂,适合入门和作为工具书平时查阅
附:
ctrl+c #结束当前任务
ctrl+z #挂起当前任务
jobs -l #查看任务,返回任务编号 和 进程号
bg %n #编号n的任务转向后台运行,实际上bg n 也可以
fg %n #编号n的任务转向前台运行
转载请注明来源:
viencoding.com版权所有,允许转载,但转载请注明出处和原文链接: https://viencoding.com/article/6
欢迎小伙伴们在下方评论区留言 ~ O(∩_∩)O
linux断开会话不中断进程,Linux让进程后台运行且连接断开不影响(nohup、setsid、disown、screen)...相关推荐
- linux进程后台运行的几种方法 - nohup/setsid//disown/screen
我们经常会碰到这样的问题,用 telnet/ssh 登录了远程的 Linux 服务器,运行了一些耗时较长的任务, 结果却由于网络的不稳定导致任务中途失败.如何让命令提交后不受本地关闭终端窗口/网络断开 ...
- Linux运行与控制后台进程的方法:nohup, setsid, , disown, screen
我们经常会碰到这样的问题,用ssh登录了远程的Linux服务器,运行了一些耗时较长的任务,结果却由于网络等的不稳定导致任务中途失败. 这是由于在用户注销(logout)或者网络断开时,终端会收到 HU ...
- Linux 将进程放入后台执行,解决网络,ssh断开导致进程结束(nohup, setsid, , disown)...
Linux 将进程放入后台执行,解决网络,ssh断开导致进程结束(nohup, setsid, &, disown) 1.nohup 命令 我们知道,当用户注销(logout)或者网络断开 ...
- linux scp 跨服务器,scp跨服务器拷贝,后台运行
[转载]原文:https://blog.csdn.net/u013091013/article/details/68941250 通常情况下,我门在同一台服务器拷贝数据最常用的命令便是cp,如果要在不 ...
- linux下如何部署本jar包并且在后台运行
执行jar包的命令和在windows操作系统上没有任何区别: 1 先找到自己jar包放在的绝对路径 2 java -jar 跟你jar的绝对路径 3 将jar程序设置成后台运行,并且将标准输出的日志重 ...
- Linux忘记将任务放后台 不能终止程序 将前台任务放在后台继续运行 (nohup, setsid, , disown)
本文链接:https://blog.csdn.net/weixin_40015791/article/details/103621927 今天将任务在服务器跑上,但是忘记放后台了,运行了七八个小时又不 ...
- 让进程在后台可靠运行的几种方法 nohup,setsid,,disown,CTRL-z ,screen
让进程在后台可靠运行的几种方法 几年前在developerWorks上面看到的文章,感觉非常实用,又简单整理了一下,转到这里,希望给看到的人带来一些帮助.文中提到的nohup和subshell方式一直 ...
- linux断开会话不中断进程,Linux screen 解决会话终止当前进程断开的问题
使用原因: 远程到服务器,经常运行一些需要很长时间才能完成的任务,比如备份数据,传输数据等.通常情况下我们都是为每一个这样的任务开一个远程终端窗口,因为它们执行的时间太长了.必须等待它们执行完毕,在此 ...
- linux块设备驱动中断程序,linux设备驱动归纳总结(六):1.中断的实现
linux设备驱动归纳总结(六):1.中断的实现 xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ...
最新文章
- 第十八课 色彩样式与滤镜
- VTK:模型之FinanceFieldData
- java toast_Android中Toast的用法简介
- wincc服务器系统,什么情况下用wincc服务器与客户端
- imx6q 开发android,SAIL-IMX6Q ANDROID开发环境搭建与系统编译
- strcpy()、memcpy()、memmove()、memset()及其应用
- Jmeter如何将返回值作为下一接口的参数?
- java.lang.UnsatisfiedLinkError: JNA support (com/sun/jna/android-arm/libjnidispatch.so) not found
- DDZY719-Z型单相费控智能电能表通过Rola模块实现的无线抄表实验
- Adobe Flash Player不是最新版本,导致视频无法播放?
- ps两张图片合在一起
- 计算机共享在哪里找,电脑共享文件在哪里找
- 【C语言】数组和函数
- 【程序设计训练】1-7 F1方程式冠军
- python程序设计与案例教程王小银_《Python程序设计与案例教程》王小银著【摘要 书评 在线阅读】-苏宁易购图书...
- Unity_回合制战斗系统_01
- 雷军2001年去搜狐见张朝阳不是为面试 而是给卓越网拉融资
- 麻将番型计算(二人麻将)
- javaScript:结合mousedown、mousemove、mouseup事件,实现拖动方块在页面内移动(代码)
- 内核中的互斥锁的使用