Linux保持命令在后台运行的几种方法及原理
记录一下Linux下使命令不受终端断开的影响,保持在后台运行的几个方法及其原理。当用户注销logout或者网络中断时,终端会受HUP(hangup)信号从而关闭其所有子进程。
## 两种中断信号:
1)sigint:signal interrupt,ctrl+c会发送此信号,主动关闭程序
2)sighup: signal hang up,关闭终端,网络断线,关闭屏幕会发送此挂断信号。
解决方法大体有两种:要么让进程忽略HUP信号,要么让进程运行在新的会话里从而成为不属于此终端下的子进程。下面分别介绍几种方式,如果亲自动手验证一番会更有收获。
1、nohup命令可以让要执行的命令忽略HUP信号,再加上&可以保证命令一直在后台运行。
nohup ./test.sh > out.log 2>err.log &
后台不中断执行./test.sh,stdout输出给out.log,stderr输出给err.log
例:nohup commandXXX > test.log 2>&1 &
命令解析:含义是把stderr也重定向给stdin
nohup可以让commandXXX这个命令忽略HUP信号;
第一个>代表将命令的标准输出重定向到指定的地方,这里是test.log
2>&1代表重定向标准错误重定向到标准输出,这里标准输出已经被重定向到test.log,所以标准错误也会输出到test.log。这里引申一下:
Linux中的标准输入即STDIN , 在/dev/stdin ,一般指键盘输入, shell里代号是0;
Linux中的标准输出STDOUT, 在/dev/stdout,一般指终端(terminal), 就是显示器, shell里代号是1;
Linux中的标准错误STDERR,在/dev/stderr也是指终端(terminal),不同的是,错误信息送到这里 shell里代号是2
最后一个&表示让命令在后台运行
关闭终端后可以通过ps -ef|grep commandXXX命令查找到后台进程。
0 – stdin (standard input),
1 – stdout (standard output),显然 nohup command > out.log 等价于 nohup command 1> out.log,是缺省行为。
2 – stderr (standard error)
2、setsid命令可以让进行运行在新的会话下,即不属于当前终端的子进程。那么即使当前终端发出了HUP信号,也不会影响该进程
例:setsid commandXXX
其实通过观察进程中的父进程号(PPID)发现一些端倪,使用setsid后进行的PPID为1(即为init进程ID),并非当前终端的进程ID。
3(本地单元测试通过)将一个或多个命令用()括起来在shell中运行,所提交的作业并不在作业列表中,即无法通过jobs查看到。新提交的进程的PPID为1。
例:(commandXXX)
4、若未加上述任何处理就执行了命令,如何补救才能让其不受HUP信息的影响呢?
答案是作业调度。对于某个已执行的命令,经过以下几个步骤可以让其忽略HUP信号:
- 先使用ctrl+z命令将正在执行的命令变为job作业,;
- 使用jobs可以查看到具体的作业号(jobid);
- 再用bg %jobid命令让其在后台运行;
- 最后使用disown -h %jobid 即可使该作业忽略HUP信号
4.1 ctrl + z
将一个正在前台执行的作业进程放到后台,并且暂停,用术语讲就是挂起,执行后如下:
[1]+ Stopped ./test.sh
4.2 jobs
查看当前有多少在后台运行的命令,[jobnumber] 就是作业号。
jobs
[1]+ Stopped ./test.sh
[2]+ Running ./test2.sh &
4.3 bg
将后台中暂停(挂起)的作业进程继续运行,例如把1号作业(./test.sh) 放到后台运行,注意看已经带了&
bg 1
[1]+ ./test.sh &
4.4 fg
将后台中的作业进程调至前台继续运行,例如把2号作业(./test2.sh &)调至前台运行
fg 2
./test2.sh
5、有大量这种需要稳定的在后台运行的命令时,如何避免对每条命令都做上述的重复操作呢?
5.1 介绍
答案是screen。screen提供了ANSI/VT100的终端模拟器,能够在一个真实终端下运行多个全屏的伪终端。screen具有很多参数,功能强大,在此仅简要分析一下为什么使用screen可以避免HUP信号的影响:
我们可以粗略地认为screen是一个虚拟终端软件,直接在linux系统里面启动了另外一个后台程序接管(维持)了你的终端会话,当你直接连接的终端ssh断开时他仍然让程序认为你的ssh持续链接着,这样也就不会出现进程接收到中断信号而退出。
- 用screen -dnS session new 建立一个处于断开模式下的会话(并指定其会话名);
- 用screen -list 列出所有会话;
- 用screen -r session name 重新连接指定会话;
- 用ctrl -a D暂时断开当前会话;
5.2 安装
yum -y install screen
5.3 使用
1)新建会话
screen -S yourname -> 新建一个叫yourname的session
2) 列出当前所有的session
screen -ls
3)恢复会话(回到yourname这个session)
screen -r yourname
4) detach某个session
screen -d yourname -> 远程detach某个session
screen -d -r yourname -> 结束当前session并回到yourname这个session
5)删除会话
screen -S pid-X quit
当我们用-r连接到screen会话时,就进入了一个伪终端,不会再受到HUP信号的影响了。
6、其他命令:
-
pstree -H pid 查看进程号对应的进程命令的树形结构
-
fg %jobid 将某个挂起的进程放回前台
-
bg %jobid 将某个挂起的进程调到后台继续运行,这一点在调试代码时尤其有用,因为将代码编辑器挂起到后台再重新返回时,光标定位仍停留到上次挂起时的位置,避免了重新地凝望的麻烦。
-
ctrl +c 停止当前命令
-
jobs -l 列出所有任务的pid,jobs的状态可以是running/stopped/terminated,但若任务终止了(kill),shell会从当前列表中删除任务的进程标识。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 一文读懂知识蒸馏
· 终于写完轮子一部分:tcp代理 了,记录一下
2018-07-19 Java中的访问修饰符
2016-07-19 JSP/Servlet Web应用中.properties文件的放置与读取
2016-07-19 Java中Properties类的操作