基本概念
在单一终端机下同时进行多个工作的行为管理称为Job Control。其实说的简单点就是在一个登录窗口下可以同时进行多个工作任务,比如我们在登录bash后,想要一边复制文件一边进行数据查找,一边进行编译,还可以一边进行vi程序编写。其实这些工作可以同时在一个shell中进行,这时就需要了解下linux的job control的使用。
如何进行job control管理
那么如何进程linux job control管理,要进行job control管理,需要通过job控制命令来进行,下面一一介绍job control相关的命令:
直接将命令丢到后台中执行的&:
命令后面跟&符号可以将命令的执行丢到后台去执行,不需要等待当前命令结束后才可以继续执行其他命令,这样就可以实现在同一bash下进行多个任务了,注意这里所说的是丢到后台执行,不是在后台挂起。举例如下,将5个sleep程序丢到后台执行:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16[root@iZj6c43t8c5urd16vueux0Z ~]# sleep 200 &
[1] 22362
[root@iZj6c43t8c5urd16vueux0Z ~]# sleep 200 &
[2] 22363
[root@iZj6c43t8c5urd16vueux0Z ~]# sleep 200 &
[3] 22364
[root@iZj6c43t8c5urd16vueux0Z ~]# sleep 200 &
[4] 22365
[root@iZj6c43t8c5urd16vueux0Z ~]# sleep 200 &
[5] 22366
[root@iZj6c43t8c5urd16vueux0Z ~]#
[1] Done sleep 200
[2] Done sleep 200
[3] Done sleep 200
[4]- Done sleep 200
[5]+ Done sleep 200可以看出每将一个任务丢到后台执行后,都会输出用中括号扩起来的job id以及该命令的PID,格式为:[job number] PID,在任务完成后会输出提示信息,表示该任务的完成状态,格式为:[job number] 任务完成状态 任务命令行,在上面输出中,后面两个任务的job id后面分别有个-和+这两个符号,+代表这个任务是最新添加的,-代表最近最后第二个被放置到后台的任务,如果超过最后第三个以后的任务,就不会有+/-符号的存在了,Done表示任务完成,sleep 200表示这个任务的命令行。
将目前的工作丢到后台中暂停:[ctrl]-z:
有时候我们可能需要将当前的工作暂时挂起(暂停执行),需要在同一shell下临时处理其他工作。比如我正用vim编辑一个文件,突然想起要看下系统当前时间是几点了,这时就可以先将vim挂起到后台,然后执行date命令查看时间,完了后再将挂起的工作唤醒,继续工作。举例如下:1
2
3
4
5
6[root@iZj6c43t8c5urd16vueux0Z ~]# vim hello.sh # 打开文件编辑,按ctrl+z将vim暂时挂起,执行其他命令
[1]+ Stopped vim hello.sh # 表示已将vim挂到后台,处于暂停状态
[root@iZj6c43t8c5urd16vueux0Z ~]# date # 此时可以执行其他任何命令
Sun Dec 17 13:02:15 CST 2017
[root@iZj6c43t8c5urd16vueux0Z ~]# fg # 执行fg将最近添加到后台的任务唤到前台来执行,在此执行fg继续vim编辑,关于这个命令的使用后面会介绍查看目前的后台工作状态:jobs:
如果想要知道目前有多少个工作在后台当中,就可以用jobs命令来查看。jobs:
- -l 除了列出job number与命令串之外,同时列出PID的号码;
- -r 仅列出正在后台run的工作;
- -s 仅列出正在后台暂停(stop)的工作
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20[root@iZj6c43t8c5urd16vueux0Z ~]# sleep 200 &
[1] 22610
[root@iZj6c43t8c5urd16vueux0Z ~]# sleep 200 &
[2] 22611
[root@iZj6c43t8c5urd16vueux0Z ~]# sleep 200
^Z
[3]+ Stopped sleep 200
[root@iZj6c43t8c5urd16vueux0Z ~]# jobs
[1] Running sleep 200 &
[2]- Running sleep 200 &
[3]+ Stopped sleep 200
[root@iZj6c43t8c5urd16vueux0Z ~]# jobs -l
[1] 22610 Running sleep 200 &
[2]- 22611 Running sleep 200 &
[3]+ 22612 Stopped sleep 200
[root@iZj6c43t8c5urd16vueux0Z ~]# jobs -r
[1] Running sleep 200 &
[2]- Running sleep 200 &
[root@iZj6c43t8c5urd16vueux0Z ~]# jobs -s
[3]+ Stopped sleep 200
将后台工作拿到前台来处理:fg:
在前面的命令当中都是将job放到后台中处理,如果需要将后台中的job放到前台中执行,可以用fg命令。命令格式为:fg %jobnumber,注意:那个%是可选的。如果直接执行fg,后面不加jobnumber,则默认将最后放到后台的job调到前台,如果要指定要将需要的job调到前台,则可以先用jobs获取到jobnumber,然后fg指定需要的jobnumber即可将对应的job调到前台。1
2
3
4
5
6
7
8
9
10
11
12
13
14[root@iZj6c43t8c5urd16vueux0Z ~]# sleep 200 &
[4] 22640
[root@iZj6c43t8c5urd16vueux0Z ~]# sleep 200 &
[5] 22641
[root@iZj6c43t8c5urd16vueux0Z ~]# sleep 200
^Z
[6]+ Stopped sleep 200
[root@iZj6c43t8c5urd16vueux0Z ~]# jobs
[3]- Stopped sleep 200
[4] Running sleep 200 &
[5] Running sleep 200 &
[6]+ Stopped sleep 200
[root@iZj6c43t8c5urd16vueux0Z ~]# fg 5 # 将5号job调到前台来执行
sleep 200让工作在后台下的状态变成运行中(Running):bg:
通过前面的介绍我们知道ctrl+z可以将一个job在后台暂停,状态为Stopped,那么如何将这个暂停的后台job变成Running状态呢,同时该job还在后台。我们可以用bg命令实现,命令格式为:bg %jobnumber,注意:那个%是可选的。和fg类似,直接执行bg,后面不加jobnumber,则默认将最后放到后台的job的状态变为Running。1
2
3
4
5
6
7
8
9
10
11
12
13
14[root@iZj6c43t8c5urd16vueux0Z ~]# sleep 20
^Z # 按下ctrl+z将该命令挂起到后台
[1]+ Stopped sleep 20
[root@iZj6c43t8c5urd16vueux0Z ~]# sleep 20
^Z # 按下ctrl+z将该命令挂起到后台
[2]+ Stopped sleep 20
[root@iZj6c43t8c5urd16vueux0Z ~]# jobs # 查看当前后台job的状态
[1]- Stopped sleep 20
[2]+ Stopped sleep 20
[root@iZj6c43t8c5urd16vueux0Z ~]# bg # 将最近的添加到后台的job变为Running
[2]+ sleep 20 &
[root@iZj6c43t8c5urd16vueux0Z ~]# jobs
[1]+ Stopped sleep 20
[2]- Running sleep 20 & #可以看出job号为2的job状态已经变为Running管理后台的job:kill:
如果想要删除某个job或者将该job重新启动,可以用kill命令来实现,用kill来给job一个信号(signal)。命令格式为:kill -signal %jobnumber,注意这里是jobnumber,不是PID,当然用PID也可以删除job。kill:
- -l 列出目前kill能够使用的信号有哪些
- -1 重新读取一次参数的配置文件(类似reload)
- -2 代表由键盘输入ctrl+c同样的操作
- -9 立刻强制删除一个job,一般用来终止一个异常程序
- -15 以正常的程序方式终止一个job。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21[root@iZj6c43t8c5urd16vueux0Z ~]# sleep 200 &
[1] 22701 #后台Running
[root@iZj6c43t8c5urd16vueux0Z ~]# sleep 200 &
[2] 22702 # 后台Running
[root@iZj6c43t8c5urd16vueux0Z ~]# sleep 200
^Z # ctrl+z 后台暂停
[3]+ Stopped sleep 200
[root@iZj6c43t8c5urd16vueux0Z ~]# jobs
[1] Running sleep 200 &
[2]- Running sleep 200 &
[3]+ Stopped sleep 200
[root@iZj6c43t8c5urd16vueux0Z ~]# kill -15 %3 # 注意,这里必须得加%,表示job号码,为了区分jobnumber和PID
[3]+ Stopped sleep 200
[root@iZj6c43t8c5urd16vueux0Z ~]# jobs
[1] Running sleep 200 &
[2]- Running sleep 200 &
[3]+ Terminated sleep 200 # 3号job已删除
[root@iZj6c43t8c5urd16vueux0Z ~]# jobs
[1]- Running sleep 200 &
[2]+ Running sleep 200 &
脱机管理问题:
需要注意的是上面所说的将job放到后台并不是放到系统的后台去,只是放到当前shell环境的后台,在这种情况下,如果你以远程的连接方式连接到你的Linux主机,并且将job以&的方式放到后台去,当exit退出终端后,后台执行的job将会被中断。可以自己做个实验验证,在此不试验了。那么如何实现将job正真放到系统后台呢,即使exit退出终端job还可以继续工作。其实很简单,用nohup命令配合&即可,示例如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14[root@iZj6c43t8c5urd16vueux0Z ~]# nohup sleep 200 &
[1] 22721
[root@iZj6c43t8c5urd16vueux0Z ~]# nohup: ignoring input and appending output to ‘nohup.out’
[root@iZj6c43t8c5urd16vueux0Z ~]# ps aux | grep sleep | grep -v grep
root 22721 0.0 0.0 107892 604 pts/1 S 15:21 0:00 sleep 200
[root@iZj6c43t8c5urd16vueux0Z ~]# exit # 退出终端
logout
Connection to 47.91.229.209 closed.
# haohao @ MacBook-Pro-8 in ~ [15:23:15]
$ sh hk.sh # 重新登录, 查看进程是否还在
[root@iZj6c43t8c5urd16vueux0Z ~]# ps aux | grep sleep | grep -v grep
root 22721 0.0 0.0 107892 604 ? S 15:21 0:00 sleep 200
# 可以看出进程依然存在,并没有终止
总结
有了job control机制,我们可以灵活地同时在一个终端窗口执行多个任务,不需要打开多个终端来实现多任务,提高了工作的效率。另外还可以随时查看和管理后台job的状态,不过job control只适用于当前工作的shell环境,如果退出shell环境,那么所有的job都将退出,所以如果需要某个job永久在后台执行,不依赖于当前shell环境的存活,可以使用nohup来将任务放到系统后台来执行。