# 工作管理(job control)
是在 bash 环境下的概念,当我们登录系统取得 bash shell 后,在单一终端机下同时进行多个工作的行为管理。
# 什么是工作管理?
进行工作管理的行为中,其实每个工作都是目前 bash 的子进程,彼此之间是有相关性的。我们无法以 job control 的方式由 tty1 的环境去管理 tty2 的 bash
为什么会有工作管理?系统有多个 tty 使用,这样切换很麻烦,还有之前讲解的 /etc/security/limits.conf(第 13 章)
可以设置同时登录的联机数量,假设只允许一个呢?
假设我们只有一个终端机接口,因此在可以出现提示字符让你操作的环境称为 前景 foreground,其他工作可以放入 背景 background 去暂停或运行。要注意的是:放入背景的工作在运行时,不能与使用者互动。比如 vim 不能再背景里面执行(running)的,因为你没有输入数据它就不会运行。而且放入背景的工作是不可以使用 ctrl+c 来终止的
进行 bash 的 job control 必须要注意的限制是:
- 这些工作所触发的进程必须来自于你的 shell 的子进程(只管理自己的 bash)
- 前景 foreground:你可以控制与下达指令的环境
- 背景:可以自动运行的工作,你无法使用 ctrl + c 终止它,可以使用 bg、fg 呼叫该工作
- 背景中执行的进程不能等待 terminal/shell 的输入(input)
# job control 的管理
# 直接将指令丢到背景中 执行 的 &
# 使用 & 将 /etc/ 整个备份为 /tmp/etc/tar.gz 工作丢到背景中执行
# 原因就是,压缩费时,不想一直就在当前界面看着他完成
[root@study ~]# tar -zpcf /tmp/etc.tar.gz /etc &
[1] 19763 # job number 与 PID
[root@study ~]# tar: Removing leading `/' from member names
# PID 与 bash 的控制有关,后续出现的数据信息是 tar 执行的数据流
# 由于没有加上数据流重导向,所以会影响画面,不过不会影响前景的操作
# 那他什么时候完成呢?当你输入几个指令后,发现出现了这一行
# 那么久表示在背景中的工作已经完成了
[1]+ Done tar -zpcf /tmp/etc.tar.gz /etc
2
3
4
5
6
7
8
9
10
11
[1]+
表示这个工作已经完成(Done),后面是具体的指令串。如果有有信息出现,那么你的前景会出现干扰,只需要按下 enter 键就会出现提示字符,更下下指令
[root@study ~]# tar -zpcvf /tmp/etc.tar.gz /etc &
由于输出了信息,stdout 和 stderr 都会输出到屏幕上,这样就会影响前景终端,所以一般都利用数据流重导向,将输出数据传送至某个文件中,比如
[root@study ~]# tar -zpcvf /tmp/etc.tar.gz /etc > /tmp/log.txt 2>&1 &
[1] 16592
[root@study ~]#
2
3
# 将 目前 的工作丢到背景中_暂停_:ctrl+z
考虑这个场景,我正在使用 vim,却发现某个文件的路径不记得了,需要到 bash 环境下进程搜索,此时不需要结束 vim,可以把它丢到背景中等待
[root@study ~]# vim ~/.bashrc
# 在 vim 环境下按 ctrl + z 组合键
[2]+ Stopped vim ~/.bashrc
[root@study ~]# # 这就取得了前景
[root@study ~]# find / -print
# 会大量输出信息,我们把这个工作也丢到背景中执行
[3]+ Stopped find / -print
[root@study ~]#
2
3
4
5
6
7
8
[2]+
表示这个是加入到背景中的第二个工作,Stopped 是状态,预设情况下,使用 ctrl+z 丢到背景中的工作都是暂停状态
# 观察目前的背景工作状态:jobs
jobs [-lrs]
选项与参数:
-l:除了列出 job number 与指令之外,同时列出 PID 的号码
-r:仅列出正在背景 run 的工作
-s:仅列出正在背景中暂停 stop 的工作
2
3
4
5
6
# 范例 1:观察目前的 bash 中,所有工作与队友的 PID
[root@study ~]# jobs -l
[2]- 26476 Stopped vim ~/.bashrc
[3]+ 2207 Stopped find / -print
2
3
4
仔细看上面有减号和加号:
+
:表示最近被放到背景的工作;如果只输入 fg 指令,那么[3]
会被拿到前景中来处理-
:表示最近最后第二个被放置到背景中的工作。如果超过最后第三个以后的工作,就不会有-、+
符号了
# 将背景工作拿到前景来处理:fg
fg %jobnumber
$jobnumber: jobnumber 是工作号码(数字),哪个 % 是可有可无的
2
3
# 范例 1:先以 jobs 管擦工作,再将工作取出
[root@study ~]# jobs -l
[2]- 26476 Stopped vim ~/.bashrc
[3]+ 2207 Stopped find / -print
# 取出 + 号的工作,注意会刷屏,马上按下 ctrl + z ,再次放入到背景中
[root@study ~]# fg
# 直接取出 2 的工作,在放到背景中
[root@study ~]# fg %2
vim ~/.bashrc
[2]+ Stopped vim ~/.bashrc
[root@study ~]# jobs -l
[2]+ 26476 Stopped vim ~/.bashrc
[3]- 2207 Stopped find / -print
# 可以看到, 2 的工作被标记为了 + 号,表示是最近放进去的
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# 让工作在背景下的状态变成运行中:bg
# 范例 1: 执行 find / -perm /7000 > /tmp/text.txt,立刻丢到背景去暂停
[root@study ~]# find / -perm /7000 > /tmp/text.txt
find: '/proc/29541/task/29541/fd/5': No such file or directory
find: '/proc/29541/task/29541/fdinfo/5': No such file or directory
find: '/proc/29541/fd/6': No such file or directory
find: '/proc/29541/fdinfo/6': No such file or directory
^Z
[4]+ Stopped find / -perm /7000 > /tmp/text.txt
# 范例 2:让该工作在背景下进行,并且观察他
[root@study ~]# jobs ; bg %4; jobs
[2]- Stopped vim ~/.bashrc
[3] Stopped find / -print
[4]+ Stopped find / -perm /7000 > /tmp/text.txt
[4]+ find / -perm /7000 > /tmp/text.txt &
[2]+ Stopped vim ~/.bashrc
[3] Stopped find / -print
[4]- Running find / -perm /7000 > /tmp/text.txt &
# 第 4 个由 Stopped 变成了 Running 状态
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 管理背景中的工作:kill
通过 fg 拿到前景来,可以通过 kill 将该工作直接移除
kill -signal $jobnumber
kill -l
选项与参数:
-l:L 的小写,列出目前 kill 能够使用的信号(signal)有哪些?
signal:给予后续工作什么指示,用 man 7 signal 可知:
-1:重新读取一次参数的配置文件(类似 reload)
-2:代表与由键盘输入 ctrl+c 同样的动作
-9:立刻强制删除一个工作
-15:已正常的进程方式终止一项工作。与 -9 是不一样的
2
3
4
5
6
7
8
9
10
范例 1: 找出目前 bash 环境下的背景工作,并将该工作 强制删除
[root@study ~]# jobs
[2]+ Stopped vim ~/.bashrc
[3] Stopped find / -print
[4]- Exit 1 find / -perm /7000 > /tmp/text.txt
[root@study ~]# kill -9 %3; jobs
[2]+ Stopped vim ~/.bashrc
[3] Killed find / -print
# 过几秒再运行 jobs 会发现 killed 的不见了
# 范例 2:找出目前 bash 环境下的而背景工作,并将该工作 正常 终止
[root@study ~]# kill -SIGTERM %2
[2]+ Stopped vim ~/.bashrc
[root@study ~]# jobs
[2]+ Stopped vim ~/.bashrc
# -SIGTERM 与 -15 同效果,可以用哪个 kill -l 来查阅
# 在这个案例中,会发现 vim 的工作无法被结束,无法通过 kill 正常终止
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
使用 vim 时候,会产生一个 .filename.swp
文件,使用 -15 这个 signal 时,vim 会尝试以正常的步骤来结束掉该 vi 的工作,使用 .filename.swp
会主动的被移除,若是使用 -9,那么 swp 文件不会被移除调用
kill 需要了解 1、9、15 的 signal 的含义,可以用 man 7 signal 查询相关资料,还有一个 killall 也是同样的用法。
kill 后面接的数字,默认是 PID,要管理 bash 的工作控制,需要加上 %数字 的方式
# 脱机管理问题
注意:前面工作管理中的「背景」是指在终端机模式下可以避免「ctrl+c」中断,可以理解为是这个 bash 的背景,并 不是放到系统的背景 中去。所以,工作管理的背景依旧与终端机有关
如果你是以远程方式连接到 Linux 主机,并且将工作以 & 的方式放到背景中去,在工作未结束时,你脱机了,该工作不会继续进行,而是会被中断掉
那么可以使用前一章学习的 at 指令,因为它是将工作放置到系统背景,还可以使用 nohup 指令来达到效果
nohup [指令与参数] # 在终端机前景中工作
nohup [指令与参数] # 在终端机背景中工作
2
TIP
nohup 后面的指令不支持 bash 内置指令!
#1. 编辑一个会随眠 500 秒的程序
[root@study ~]# vim sleep500.sh
#!/bin/bash
/bin/sleep 500s
/bin/echo "I have sleep 500 seconds."
# 2. 丢到背景中执行
[root@study ~]# chmod a+x sleep500.sh
[root@study ~]# nohup ./sleep500.sh &
[3] 14915
[root@study ~]# nohup: ignoring input and appending output to 'nohup.out'
2
3
4
5
6
7
8
9
10
11
你登出登录后,再次登录系统,使用 pstree (这里没有说是什么)去查询你的进程,会发现它还在执行,还输出了一个信息,nohup 与终端机无关了,因此整个信息的输出就会被导向 ~/nohup.out
← 什么是进程(process) 进程管理 →