一个作业是一个命令流水线。无论何时向Linux输入一个命令,其实都是在运行一个简单的作业。举例来说,在命令行输入date然后按RETURN键:此时就运行了一个作业。也可以在单个命令行里创建多个包含数条命令的作业:
$ find . -print | sort | lpr & grep -1 alex /tmp/* > alexfiles &
[1] 18839
[2] 18876
在第1个&符号之前的命令行部分是一个作业,它由一个管道连接的3个进程组成:find、sort和lpr。第2个作业是运行grep的单个进程。两个作业均被结尾的&符号放置到后台执行,因此bash没有等待这些作业完成就立即显示提示符。
使用作业控制可以将命令从前台移到后台,或者是从后台移到前台。还可以临时停止命令,以及列出所有正在后台执行的命令或者是已经停止的命令。
内置命令jobs将列出所有后台作业。下面的序列演示了输入jobs命令将会发生的事件。其中sleep在后台运行并创建了jobs报告的一个后台作业。
$ sleep 60 &
[1] 7809
$ jobs
[1] + Running sleep 60 &
shell为那些运行在后台的命令指派了作业编号。下面的示例中有几个作业在后台启动。在shell刚要发出提示符之前,它立即列出每个作业的编号和PID号。
$ xclock &
[1] 1246
$ date &
[2] 1247
$ Sun Dec 4 11:44:40 PST 2005
[2]+ Done date
$ find /usr -name ace -print > findout &
[2] 1269
$ jobs
[1]- Running xclock &
[2]+ Running find /usr -name ace -print > findout &
当作业完成之后,作业编号就被丢弃,这样作业编号就可以重用。当开始一个后台作业或者将一个作业置于后台时,shell为该作业分配一个作业编号,该编号大于当前正在使用中的最大编号。
在前面的示例中,jobs命令将第1个任务xclock列为作业1。date命令并没有出现在作业列表中,因为它在jobs运行之前已经结束了。因为date命令在find运行之前完成,所以find命令成为作业2。
为了将一个作业放置到前台执行,可以将其作业编号告诉内置命令fg。还可以通过另外一种方式实现这个功能,即在百分号后面跟着该作业的编号作为一条命令。下面的两条命令都可以将作业2移到前台执行。
$ fg 2
或者:
$ %2
也可通过百分号后跟字符串来引用作业,其中的字符串能唯一标识该作业的命令行起始部分。与前面的命令不同,用户可以使用fg %find或者fg %f,因为它们都可以唯一标识作业2。如果在百分号后面跟着一个问号和一个字符串,那么该字符串将和命令行中的任意部分进行匹配。在前面的示例中,fg %?ace也可以将作业2放置到前台执行。
常常将唯一一个运行在后台的作业或者是jobs列表中带加号(+)的那个作业放置到前台执行。在这些情况下使用fg,就不必带任何参数。
在将一个前台作业转移到后台执行之前,必须首先按下挂起键(通常是CONTROL+Z)将其挂起(暂时停止运行)。按下挂起键会立即将前台任务挂起。然后就可以使用内置命令bg将该任务放置到后台运行。
$ bg
如果某个后台作业尝试从终端进行读取操作时,shell将停止该作业,并通知用户该作业已被停止并等待输入。此时用户必须将该作业转移到前台,这样该作业就可以从终端读取输入。当该作业转移到前台时,shell将显示其命令行。
$ (sleep 5; cat > mytext) &
[1] 1343
$ date
Sun Dec 4 11:58:20 PST 2005
[1]+ Stopped ( sleep 5; cat>mytext )
$ fg
( sleep 5; cat >mytext )
Remember to let the cat out!
CONTROL-D
$
在这个示例中,shell在其开始执行时尽可能快地显示后台作业的任务标号和PID号,然后给出了一个提示符。此时输入一条命令,用户输入的是命令date,它的输出将立即出现在屏幕上。shell将等待直到它发出提示符以通知用户作业1停止(在date结束后)。当用户输入fg命令时,shell把在后台运行的作业放置到前台,这时可以输入该命令正在等待的输入。在这种情况下,输入结束时需要按下CONTROL+D表示EOF(文件结束)。然后shell显示另一个提示符。
当作业的状态发生改变时,shell将通知用户,以提醒某个后台作业开始、完成或者因为等待终端输入而被停止。当某个前台作业被挂起时,shell也将通知用户。因为关于正在后台运行的作业的通知可能扰乱用户的手头工作,所以shell将这些通知延迟到在它显示提示符之前才显示给用户。可以通过设置notify使shell无延迟地显示这些通知。
如果用户在尚有作业停止的时候退出,shell将发出一条警告,并且不允许用户退出。此时,如果使用jobs浏览作业列表或者是立即再次试图离开,那么,shell将允许用户离开并中止那些被停止的作业。那些在后台运行(但是并没有被停止)的作业将继续运行。在下面的示例中,在第2个exit中止了shell之后,find(作业1)将继续运行,但是cat(作业2)被中止了:
$ find / -size +100k > $HOME/bigfiles 2>&1 &
[1] 1426
$ cat > mytest &
[2] 1428
$ exit
exit
There are stopped jobs.
$ exit
exit
login: