作业控制
在本课程中,你将学习什么是作业控制,以及如何在 shell 中管理和运行多个作业。
这一课的重要性
作业控制是 Bash 的核心功能,如果你每天都在使用 Bash,那么理解这一概念至关重要。
启动作业
你将学习如何使用 sleep 命令运行一个简单的作业。
输入以下命令:
1sleep 60 &
你输入了一个“普通”命令(sleep 60),然后添加了一个字符——与号(&)。这个 & 会将命令在后台运行,从而成为当前 Bash 会话中的一个 作业。
该 作业 有两个标识符,它们会立即显示在终端中:
1[1] 39165
第一个是 作业号,这里是 1;第二个是 进程标识符,这里是 39165,但对你来说可能不同。
如果在时间结束前你执行其他命令:
1pwd
这些命令不会受到正在运行的作业干扰。你可以照常继续操作。
如果你等待程序完成(本例中为 60 秒),然后执行其他命令,Bash 会告诉你该作业的状态。例如,等待后输入:
1true
你会看到终端输出:
1[1]+ Done sleep 60
再次显示了作业号,这次附带状态(Done)以及最初运行的命令(sleep 60)。
控制作业
与启动作业类似,你也可以通过发送信号来控制作业。
现在你将启动两个作业:一个睡眠两分钟,另一个多睡一秒(以便区分它们)。
1sleep 120 & 2sleep 121 &
现在你有两个作业在后台运行。你可以使用 jobs 内建命令查看它们的状态:
1jobs
你应该看到如下输出:
1[1]- Running sleep 120 & 2[2]+ Running sleep 121 &
每个作业都用方括号中的数字标识,后面跟着加号或减号。加号表示当你运行 fg 内建命令时,该作业将被带到前台。
现在我们来做这件事:
1fg
这次你应该看到:
1sleep 121
sleep 121 进程现在在前台运行。Bash 通过将前台命令输出到终端来通知你这一点。
现在按 \C-z 发送 STOP 信号给前台进程:
1[2]+ Stopped sleep 121
再次看到作业号、加号和状态(Stopped)。如果你想让进程继续运行,需要使用 bg 内建命令:
1bg
现在你应该看到:
1[2]+ sleep 121 &
进程已从暂停状态恢复运行。如果你花超过两分钟完成上述操作,可能会收到进程已终止的消息,提示其状态为 Done。如果是这样,请重新运行两个 sleep 命令,回到此处继续。
现在两个 sleep 作业都在后台运行,你可以向它们发送其他信号。例如,可以终止它们:
1kill %1
1[1]+ Terminated: 15 sleep 120
百分号后跟数字称为 作业指定,这是告诉 Bash 操作特定作业编号的方式。当然,你也可以使用进程标识符来发送信号。
等待
在 Bash 脚本中,一种有用的技巧是启动多个后台进程,然后等待它们全部完成后再继续执行。这可以通过 wait 内建命令实现。
如果你原来的 sleep 作业仍在运行,可以运行 wait:
1wait
最终,wait 命令返回,并报告该进程的状态为 Done:
1[1]+ Done sleep 120
通常情况下,wait 总是返回退出码 0。但如果你加上作业指定,wait 会返回最后一个完成作业的退出码。
1sleep 20 & 2sleep 30 && false & 3wait %1 %2
那么这个 wait 会报告什么退出码?可以用以下命令检查:
1echo $?
挑战:如果将上面的 sleep 时间 20 和 30 互换,结果会怎样?
你学到了什么
-
使用信号进行 作业控制
-
作业指定 的使用
-
fg和bg内建命令 -
wait内建命令
接下来
接下来我们将学习 陷阱 和 信号。
练习
1)编写一个脚本,在后台运行一系列有用的维护或报告命令,然后在所有任务完成后输出一条总结消息。
Quiz
后台运行进程时的输出之一是