为什么写这个呢,起因是看到了这个。。。
然后这是当事人的匿名回复
学好linux多重要(
几个概念
进程
linux 下的进程(Process)分为两种,一种叫做前台进程,一种叫做后台进程,还有一种叫做守护进程。
前台进程顾名思义,是在前台与用户交互的进程,用户可以通过终端来进行交互式的控制。此类进程运行时会占用终端,用户无法启动其它程序。
后台进程与前台进程的区别就是后台进程不会占用终端,用户可以在终端启动其它程序,但输出仍会发到终端的界面。
守护进程在服务端很常见,比如Web服务器的httpd
,数据库的mysqld
等,这类进程已经完全脱离终端,生命周期比较长。
linux 会给每个进程分配一个唯一编号,叫做PID。
进程组
进程组(Process Group)是一堆进程的集合,因为进程之间往往是相互关联的,这时候可以把进程归为一组,便于操作。进程组的编号PGID取决于组长进程的PID。只要进程组当中有一个进程存在,那这个进程组就存在,不管组长进程是不是停止
作业
作业(Job)和进程组是类似的,只不过由作业里的进程产生的子进程不会属于这个作业。
会话
当用户登录系统之后就会产生一个会话(Session),一个会话包含一个会话控制进程(负责终端和系统的连接),一个前台进程组,若干个后台进程组。在会话中开启的进程都会成为改会话的子进程。
终端退出时会发生以下情况1
- 终端关闭时,信号(SIGHUP)被发送到session首进程以及作为job提交的进程(即用 & 符号提交的进程)
- session首进程退出时,该信号被发送到该session中的前台进程组中的每一个进程
- 若父进程退出导致进程组成为孤儿进程组,且该进程组中有进程处于停止状态(收到SIGSTOP或SIGTSTP信号),该信号会被发送到该进程组中的每一个进程。
如何产生后台进程
目标
现在假设你也碰到了问题中的情况,程序没跑完,又怕关屏幕后程序中断怎么办?
其实也不难分析,关闭终端的时候会发生以下事情:
所以我们要实现以下目标:
- 让前台进程成为后台进程
- 让这个后台进程不受
SIGHUP
信号的影响而终止
方案
nohup 与 &
nohup
指令可以运行一个命令,然后让命令忽略 SIGHUP
信号,而在命令尾部加上 &
可以使命令以后台方式运行,这时候程序会被加入到jobs里面.
默认用nohup执行命令时,命令的输出会被重定向至nohup.out
,所以一般可以用如下指令运行程序把输出重定向至/dev/null
:
1 | nohup COMMAND > /dev/null 2>&1 & |
用 nohup ... &
执行的程序仍然属于控制程序的子程序,所以关闭终端时SIGHUP
信号还是会发送给程序,只不过被 nohup
给忽略了。关闭终端之后,这个后台进程失去了父进程,成为了孤儿进程,会被init进程收养。
setsid
setsid
指令可以为指令开启一个新的会话,这样一来指令就不受当前终端影响了:
1 | setsid COMMAND |
ctrl-z, bg, fg, disown
如果程序忘了加 nohup 就执行了,又不想重新开始怎么办。
这时候ctrl-z
就派上用场了,如果命令在前台运行时,用户按下了ctrl-z
,那这个运行中的命令会被暂停,然后加入 jobs 里,例如
1 | ~ $ sleep 1000 |
然后可以使用 bg %jobs里的编号
使程序在后台继续运行,或者用 fg %jobs里的编号
使程序继续在前台运行。1
2
3
4~ $ jobs
[1] + suspended sleep 1000
~ $ bg %1
[1] + 5733 continued sleep 1000
disown
指令可以把进程移出作业,使其成为后台进程,关闭终端时就不会收到SIGHUP
信号,