热度 7 ||
简介:了解 Linux® 上的进程管理:如何在前台和后台之间切换进程,找出正在运行的程序,终止进程,以及在外出时让进程继续运行。本文提供的材料可以帮助您准备 Linux 系统管理员认证 LPI 101 考试,也可以作为一般的兴趣读物。
本文深入介绍基础的 Linux 进程管理技术。您将学习如何:
本文帮助您准备 Linux Professional Institute's Junior Level Administration (LPIC-1) 考试的 103 主题下的 103.5 考核目标。该考核目标的权值为 4。
为了从本文获得最大的收益,您应该具备基础的 Linux 知识,并且具有一个能够正常运行的 Linux 系统,您将在 Linux 系统上练习本文讨论的命令。不同版本的程序输出的结果的格式可能不同,因此您的结果可能与本文图片和清单所示的结果有所不同。本文的例子显示的结果来自于 Ubuntu 9.10 (Karmic Koala) 发行版。
您只要停下来仔细思考一下就会发现,除了本系列早期文章讨论的终端程序之外,您的电脑还运行着许多其他程序。事实上,如果您使用图形化桌面,您可能一次打开了多个终端窗口,或者打开了文件浏览器、Internet 浏览器、游戏、电子表格或其他应用程序。我们以前介绍的例子已经演示了在一个终端窗口中输入的命令。您要等待该命令运行完毕之后才能运行其他命令。在本文中,您将了解如何通过终端窗口一次运行多个命令。
当您在终端窗口运行命令时,您是在前台 运行它。大部这些命令的运行都很快,但现在假设您运行的是图形化桌面,并且想在桌面上显示一个数字时钟。尽管大部分图形化桌面都有一个时钟,我们仍然以此作为例子。
如果您安装了 X Window System,您也许会拥有一些实用程序,比如 xclock 或 xeyes。如果您还没有安装这些实用程序,您可以在名为 xorg-x11-apps 或 x11-apps 的包中找到它们。这两个包中的实用程序都可以在本例中使用,但我们选择使用 xclock。根据实用程序的手册页,您可以通过以下命令在图形化桌面上启动数字时钟:
xclock -d -update 1
-update 1 部分请求每秒钟更新一次;如果取消该选项,时钟将每分钟更新一次。让我们在终端窗口中运行该命令。您将看到一个类似于图 1 的时钟,您的终端窗口类似于清单 1。如果您没有 xclock 或 X Window System,稍后您将看到如何在终端窗口中创建一个简易的数字时钟。现在,您先根据本文的步骤学习,并以该时钟作为例子进行练习。
注意:在撰写本文时,有一个 bug 在启用桌面效果时会影响 xclock。最明显的影响是标题栏不变化,即使操作它时也是这样。如果您的 xclock 例子与本文的不同,您可能要关闭桌面效果一段时间。

ian@attic4:~$ xclock -d -update 1
不幸的是,您的终端窗口不再出现命令提示符,因此您要恢复它。幸好 Bash shell 有一个暂停 键 Ctrl-z。按下该组合键将恢复终端提示符,如清单 2 所示。
ian@attic4:~$ xclock -d -update 1 ^Z [1]+ Stopped xclock -d -update 1
xclock 数字时钟仍然出现在桌面上,但它已经停止运行。事实上,如果您拖动另一个窗口让它与时钟的一部分重叠,时钟被重叠的部分仍然会保持不变。注意,终端输出消息显示 “[1]+ Stopped”。该消息中的 1 表是作业编号。您可以通过输入 fg %1 重新启动时钟。您还可以通过输入 fg %xclock 或 fg %?clo 使用命令名或命令名的一部分。最后,您仅需要输入不带任何参数的 fg 就可以重新启动最近停止的作业,如本例中的 job 1。使用命令 fg 重启任务还会将其带回到前台,因此不再出现 shell 提示符。您需要做的就是将作业放回到后台;bg 命令的作业指示与 fg 命令相同,它的作用就是将作业放回到后台。
清单 3 显示如何将 xclock 作业带回到前台,并使用两种形式的 fg 命令暂停它。您可以再次暂停它并将它放到后台;此时,即使您在终端窗口运行其他程序,时钟仍会继续运行。
ian@attic4:~$ fg %1 xclock -d -update 1 ^Z [1]+ Stopped xclock -d -update 1 ian@attic4:~$ fg %?clo xclock -d -update 1 ^Z [1]+ Stopped xclock -d -update 1 ian@attic4:~$ bg [1]+ xclock -d -update 1 &
您可能已经注意到,当您将 xclock 放在后台时,该消息不再显示 “Stopped”,并且使用与符号 (&) 终止了它。事实上,您根本不需要暂停程序就可以将它放到后台;您仅需将一个与符号 (&) 添加到该命令的后面 shell 就会在后台启动该命令(或命令列表)。让我们通过该方法启动一个背景为白色的带指针时钟。您将看到类似于图 2 所示的时钟,其终端输出类似于清单 4。

ian@attic4:~$ xclock -bg wheat -update 1& [2] 4320
注意,这次显示的消息与上一次略有不同。它显示一个作业编号和一个进程 ID(PID)。我们稍后将更详细地讨论 PID 和状态。目前我们使用 jobs 命令找出有多少个作业正在运行。添加 -l 选项来列出 PID,您将看到 job 2 的 PID 为 4320,如清单 5 所示。此外还要注意,job 2 的作业编号旁边有一个加号 (+),这表明它是现正在运行 的作业。如果 fg 命令不带有任何作业指示,该作业将出现在前台。
ian@attic4:~$ jobs -l [1]- 3878 Running xclock -d -update 1 & [2]+ 4320 Running xclock -bg wheat -update 1 &
在解决其他与后台作业相关的问题之前,我们先看看一个自制的简易数字时钟。我们使用 sleep 命令将显示推迟两秒,然后使用 date 命令打印当前的日期和时间。我们将这两个命令放在一个 while 循环中,该循环带有一个用于创建无限循环的 do/done 代码块。最后,我们将所有代码放在一对圆括号中构成一个命令列表,然后使用与号将整个列表放到后台。本系列后面的文章介绍如何使用循环和脚本构建更加复杂的命令。查看我们的 学习 Linux,101:LPIC-1 路线图 了解本系列,并获得每篇文章的链接。
ian@attic4:~$ (while sleep 2; do date;done)&
[2] 4856
ian@attic4:~$ Tue Jan 19 09:23:30 EST 2010
Tue Jan 19 09:23:32 EST 2010
Tue Jan 19 09:23:34 EST 2010
fTue Jan 19 09:23:36 EST 2010
Tue Jan 19 09:23:38 EST 2010
gTue Jan 19 09:23:40 EST 2010
( while sleep 2; do
date;
done )
Tue Jan 19 09:23:42 EST 2010
Tue Jan 19 09:23:44 EST 2010
Tue Jan 19 09:23:46 EST 2010
^C
我们创建的命令列表作为 job 2 运行,其 PID 为 4856。每隔两秒钟将运行 date 命令,并且将日期和时间打印在终端窗口上。您输入的内容将突出显示。如果您的输入速度很慢,在输入完整的命令之前,您输入的字符就被几行输出隔开了。事实上,您为了将命令列表放到前台而输入的 “f” 和 “g” 相隔好几行。当您最终输入了 fg 命令之后,bash 将显示正在 shell 中运行的命令(即命令列表),该命令仍然每隔两秒钟打印输出结果。
在将作业放入前台之后,您可以终止它,或者采取其他操作。在本例中,我们使用 Ctrl-c 终止时钟。
您可能想问为什么该作业为 job 2。在终止了指针式时钟之后,仅剩下一个运行的作业,它的作业编号为 1。所以将分配下一个可用的作业编号,因此我们的简易时钟为 job 2。
在前面的例子中,来自 date 命令的输出被我们输入的 fg 命令产生的字符隔开。这导致一个有趣的问题。如果后台进程需要来自 stdin 的输入时,它会发生什么情况?
我们将在其下启动后台应用程序的终端进程称为控制终端。除非被重定向到其他地方,否则来自后台进程的 stdout 和 stderr 流将被定向控制终端。类似地,后台任务希望收到来自控制终端的输入,但是控制终端不能将您输入的任何字符定向到后台进程的 stdin。对于这种情况,Bash shell 将暂停进程,从而使它停止执行。您可以将它放到前台并提供必要的输入。清单 7 显示了一个简单的例子,在该例中可以将命令列表放到后台。在片刻之后,按下 Enter 并看到关于进程已被停止的消息。将该命令列表放到前台,添加一行输入,最后按下 Ctrl-d 表示输入文件的结尾。在命令列表运行完成之后将显示我们创建的文件。
ian@attic4:~$ (date; cat - > bginput.txt;date)& [2] 5070 ian@attic4:~$ Tue Jan 19 10:33:13 EST 2010 [2]+ Stopped ( date; cat - > bginput.txt; date ) ian@attic4:~$ ian@attic4:~$ fg ( date; cat - > bginput.txt; date ) some text more text Tue Jan 19 10:33:31 EST 2010 ian@attic4:~$ cat bginput.txt some text more text
在实际操作中,您可能想要将后台进程的标准 I/O 流重定向到文件。这涉及到另一个问题:如果控制终端关闭或用户注销,进程会发生什么情况?答案取决于所使用的 shell。如果 shell 发送 SIGHUP(或 hangup)信号,那么很可能导致应用程序关闭。我们将在稍后讨论信号,现在考虑解决该问题的另一种方法。
nohup 命令用于启动一个忽略 hangup 信号的命令,并且将 stdout 和 stderr 附加到文件。默认的文件为 nohup.out 或 $HOME/nohup.out。如果文件不可被写入,将不运行命令。如果您想要将输出指定到其他位置,那么重定向 stdout 或 stderr,参见文章 “学习 Linux,101:流、管道和重定向”。
nohup 命令将不执行管道线或命令列表。您可以将管道线或列表保存在一个文件中,然后使用 sh(默认 shell)或 bash 命令运行它。本系列的另一篇文章将显示如何让脚本文件变成可执行文件,但是在本文中我们通过 sh 或 bash 命令运行脚本。清单 8 显示了如何为我们的简易数字时钟准备脚本。将时间写到文件中用途不大,并且会造成文件不断变大,因此我们将时钟设置为每 30 秒钟更新一次,而不是每秒钟更新一次。
ian@attic4:~$ echo "while sleep 30; do date;done">pmc.sh ian@attic4:~$ nohup sh pmc.sh& [2] 5485 ian@attic4:~$ nohup: ignoring input and appending output to `nohup.out' ian@attic4:~$ nohup bash pmc.sh& [3] 5487 ian@attic4:~$ nohup: ignoring input and appending output to `nohup.out'
如果我们显示 nohup.out 的内容,我们将看到一些行,并且每个行的出现都比它前面的第二个行晚 30 秒,如清单 9 所示。
ian@attic4:~$cat nohup.out Tue Jan 19 15:01:12 EST 2010 Tue Jan 19 15:01:26 EST 2010 Tue Jan 19 15:01:44 EST 2010 Tue Jan 19 15:01:58 EST 2010 Tue Jan 19 15:02:14 EST 2010 Tue Jan 19 15:02:28 EST 2010 Tue Jan 19 15:02:44 EST 2010 Tue Jan 19 15:02:58 EST 2010
老版本的 nohup 不将状态消息写到控制终端,因此如果您做错了事情,很难立即发现。如果您将 stdout 和 stderr 重定向到自己选择的文件,您将看到老版本中出现的行为。使用 . 发出命令比输入 sh 或 bash 更加容易。清单 10 显示了按照旧方式使用 nohup 会发生什么情况,但同时重定向了 stdout 和 stderr。在输入命令之后,您将看见一条消息,它表明启动的 job 4 的 PID 为 5853。但是,再次按 Enter 将看到另一条,表明该作业已终止,退出码为 126。
ian@attic4:~$ nohup . pmc.sh >mynohup.out 2>&1 & [4] 5853 ian@attic4:~$ [4]+ Exit 126 nohup . pmc.sh > mynohup.out 2>&1
清单 11 显示了 mynohup.out 的内容。该内容没有特别之处。您使用 nohup 来在后台运行命令,并使用 source (.) 从文件运行读取命令,并在当前的 shell 中运行这些命令。这里需要记住的是,您可能需要按下 Enter 以允许 shell 显示后台作业退出状态,或者需要查看 nohup 的输出文件,看看哪里出错了。
ian@attic4:~$ cat mynohup.out nohup: ignoring input nohup: cannot run command `.': Permission denied
现在,让我们将话题转向进程的状态。如果您在此时想休息一下,那么请不要离开太久,因为您的两个作业在文件系统中创建的文件会不断变大。您可以使用 fg 命令来将它们放到前台,然后使用 Ctrl-c 终止它们。不过,如果您让它们多运行一段时间,将了解监控它们并与它们交互的其他方法。
我们在前面简单介绍了 jobs 命令,并看到了如何使用它列出作业的 Process ID(或 PID)。
我们还可以使用另一个命令 ps 来显示进程状态信息的不同部分。记住,“ps” 是 “process status” 的首字母缩写。ps 命令接受 0 个或多个 PID 作为参数并显示相关联的进程状态。如果我们将 jobs 命令与 -p 选项一起使用,输出结果将是每个作业的 process group leader 的 PID。我们将使用该输出作为 ps 命令的参数,如清单 12 所示。
ian@attic4:~$ jobs -p 3878 5485 5487 ian@attic4:~$ ps $(jobs -p) PID TTY STAT TIME COMMAND 3878 pts/1 S 0:06 xclock -d -update 1 5485 pts/1 S 0:00 sh pmc.sh 5487 pts/1 S 0:00 bash pmc.sh
如果您使用不带任何选项的 ps 命令,您将看到一个以您的终端作为控制终端的进程列表,如清单 13 所示。注意,该列表中不出现 pmc.sh 命令,但稍后您将看到为什么会这样。
ian@attic4:~$ ps PID TTY TIME CMD 2643 pts/1 00:00:00 bash 3878 pts/1 00:00:06 xclock 5485 pts/1 00:00:00 sh 5487 pts/1 00:00:00 bash 6457 pts/1 00:00:00 sleep 6467 pts/1 00:00:00 sleep 6468 pts/1 00:00:00 ps
可以通过几个选项控制所显示的信息,包括 -f (full),-j (jobs) 和 -l (long)。如果您不指定任何 PID,那么另一个比较有用的选项是 --forest,它以树结构的形式显示命令,以及每个进程对应的父进程。尤其是,您将看到前一个清单的 sleep 命令是您在后台运行的脚本的子进程。如果您刚好在不同的时间运行该命令,您将看到 date 命令列出在进程状态中,但对于该脚本,发生这种情况的几率不大。我们在清单 14 中显示其中一些选项。
ian@attic4:~$ ps -f UID PID PPID C STIME TTY TIME CMD ian 2643 2093 0 Jan18 pts/1 00:00:00 bash ian 3878 2643 0 09:17 pts/1 00:00:06 xclock -d -update 1 ian 5485 2643 0 15:00 pts/1 00:00:00 sh pmc.sh ian 5487 2643 0 15:01 pts/1 00:00:00 bash pmc.sh ian 6635 5485 0 15:41 pts/1 00:00:00 sleep 30 ian 6645 5487 0 15:42 pts/1 00:00:00 sleep 30 ian 6647 2643 0 15:42 pts/1 00:00:00 ps -f ian@attic4:~$ ps -j --forest PID PGID SID TTY TIME CMD 2643 2643 2643 pts/1 00:00:00 bash 3878 3878 2643 pts/1 00:00:06 \_ xclock 5485 5485 2643 pts/1 00:00:00 \_ sh 6657 5485 2643 pts/1 00:00:00 | \_ sleep 5487 5487 2643 pts/1 00:00:00 \_ bash 6651 5487 2643 pts/1 00:00:00 | \_ sleep 6658 6658 2643 pts/1 00:00:00 \_ ps
您已经具备一些使用 jobs 和 ps 命令监控进程的基本工具,在学习如何选择和排列进程之前,让我们简单看看其他两个监控命令。
free 命令显示系统的空闲内存和已用内存。默认情况下,使用的单位为千字节,但您可以使用选项 -b 替换为字节,使用 -k 替换为千字节,使用 -m 替换为兆字节,或使用 -g 替换为千兆字节。-t 选项显示整个行,带一个值的 -s 选项以指定的频率刷新信息。刷新时间的单位为秒,但可能是浮点值。清单 15 显示了两个例子。
ian@attic4:~$ free
total used free shared buffers cached
Mem: 4057976 1543164 2514812 0 198592 613488
-/+ buffers/cache: 731084 3326892
Swap: 10241428 0 10241428
ian@attic4:~$ free -mt
total used free shared buffers cached
Mem: 3962 1506 2456 0 193 599
-/+ buffers/cache: 713 3249
Swap: 10001 0 10001
Total: 13964 1506 12457
uptime 命令在一行内显示当前时间,系统运行时间,当前登录的用户,以及过去 1 分钟、5 分钟和 15 分钟系统的平均负载。清单 16 显示了一个例子。
ian@attic4:~$ uptime 17:41:17 up 20:03, 5 users, load average: 0.00, 0.00, 0.00
到目前为止所讨论的 ps 命令仅列出从终端会话启动的进程(注意清单 14 中的第二个例子的 SID 列,即会话 ID 列)。要通过控制终端查看所有进程,使用 -a 选项。-x 选项显示不使用控制终端的进程,-e 选项显示每一个进程的信息。清单 17 显示带控制终端的所有进程的完整格式。
ian@attic4:~$ ps -af UID PID PPID C STIME TTY TIME CMD ian 3878 2643 0 09:17 pts/1 00:00:06 xclock -d -update 1 ian 5485 2643 0 15:00 pts/1 00:00:00 sh pmc.sh ian 5487 2643 0 15:01 pts/1 00:00:00 bash pmc.sh ian 7192 5485 0 16:00 pts/1 00:00:00 sleep 30 ian 7201 5487 0 16:00 pts/1 00:00:00 sleep 30 ian 7202 2095 0 16:00 pts/0 00:00:00 ps -af
注意在 TTY 列中列出的控制终端。为了获取这个列表,我已切换到原先打开的终端窗口(pts/0),因此 ps -af 命令在 pts/0 下运行,尽管为本文创建的命令在 pts/1 下运行。
有许多针对 ps 的选项,包括控制显示哪些字段和以何种方式显示的选项。其他选项控制选择显示的进程,例如,为特定的用户(-u)或命令(-C)选择这些进程。在清单 18 中,列出了所有运行 getty 命令的进程;我们使用 -o 选项来自指定将要显示的列。我们将 user 选项添加到单纯使用 ps 获取到的常规列表,因此您可以看到哪个用户正在运行 getty。
ian@attic4:~$ ps -C getty -o user,pid,tty,time,comm USER PID TT TIME COMMAND root 1192 tty4 00:00:00 getty root 1196 tty5 00:00:00 getty root 1209 tty2 00:00:00 getty root 1219 tty3 00:00:00 getty root 1229 tty6 00:00:00 getty root 1731 tty1 00:00:00 getty
有时您需要根据特定的字段对输出进行排序,您也可以使用 --sort 选项指定要排序的字段来实现该目的。默认值为以升序的方式进行排序(+),但您也可以指定以降序的方式进行排序(-)。清单 19 显示了最终的 ps 例子,其中使用作业的格式列出了所有进程,并且根据会话 ID 和命令名对输出进程排序。首先,我们使用默认的排序;其次,我们显式地指定这两种排序方式。
ian@attic4:~$ ps -aj --sort -sid,+comm PID PGID SID TTY TIME CMD 5487 5487 2643 pts/1 00:00:00 bash 9434 9434 2643 pts/1 00:00:00 ps 5485 5485 2643 pts/1 00:00:00 sh 9430 5485 2643 pts/1 00:00:00 sleep 9433 5487 2643 pts/1 00:00:00 sleep 3878 3878 2643 pts/1 00:00:10 xclock 8019 8019 2095 pts/0 00:00:00 man 8033 8019 2095 pts/0 00:00:00 pager ian@attic4:~$ ps -aj --sort sid,comm PID PGID SID TTY TIME CMD 8019 8019 2095 pts/0 00:00:00 man 8033 8019 2095 pts/0 00:00:00 pager 5487 5487 2643 pts/1 00:00:00 bash 9435 9435 2643 pts/1 00:00:00 ps 5485 5485 2643 pts/1 00:00:00 sh 9430 5485 2643 pts/1 00:00:00 sleep 9433 5487 2643 pts/1 00:00:00 sleep 3878 3878 2643 pts/1 00:00:10 xclock
和平常一样,查看手册页详细了解您可以指定多少个选项和字段,或者使用 ps --help 命令了解简要说明。
如果您在一行内多次运行 ps,以便看看发生了什么变化,您可能需要改用 top 命令。它显示持续更新的进程列表和有用的摘要信息。清单 20 显示 top 命令输出的前几行。使用子命令 q 退出 top。
top - 16:07:22 up 18:29, 5 users, load average: 0.03, 0.02, 0.00
Tasks: 170 total, 1 running, 169 sleeping, 0 stopped, 0 zombie
Cpu(s): 2.1%us, 0.5%sy, 0.0%ni, 97.4%id, 0.0%wa, 0.0%hi, 0.0%si, 0.0%st
Mem: 4057976k total, 1543616k used, 2514360k free, 194648k buffers
Swap: 10241428k total, 0k used, 10241428k free, 613000k cached
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
6820 ian 20 0 506m 78m 26m S 1 2.0 0:23.97 firefox
1381 root 20 0 634m 40m 18m S 1 1.0 2:06.74 Xorg
2093 ian 20 0 212m 15m 10m S 1 0.4 0:13.53 gnome-terminal
6925 ian 20 0 1118m 298m 19m S 1 7.5 1:07.04 java
6855 ian 20 0 73416 11m 8808 S 1 0.3 0:05.01 npviewer.bin
7351 ian 20 0 19132 1364 980 R 0 0.0 0:00.07 top
1 root 20 0 19584 1888 1196 S 0 0.0 0:00.74 init
2 root 15 -5 0 0 0 S 0 0.0 0:00.01 kthreadd
top 命令有许多子命令,其中开始学习时最有用的子命令为:
h
获得帮助
q
退出 top 命令
f
在显示结果中添加或删除字段
o
显示顺序
F
选择需要根据其进行排序的字段
查看手册页详细了解 top 的各种选项,包括如何根据内存使用或其他标准进行排序。清单 21 显示了一个根据虚拟内存使用量以降序的方式进行排序的例子。
top - 16:21:48 up 18:43, 5 users, load average: 0.16, 0.06, 0.01 Tasks: 170 total, 3 running, 167 sleeping, 0 stopped, 0 zombie Cpu(s): 2.1%us, 0.8%sy, 0.0%ni, 96.6%id, 0.0%wa, 0.0%hi, 0.5%si, 0.0%st Mem: 4057976k total, 1588940k used, 2469036k free, 195412k buffers Swap: 10241428k total, 0k used, 10241428k free, 613056k cached PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 6925 ian 20 0 1171m 338m 21m S 0 8.5 1:44.10 java 1381 root 20 0 634m 40m 18m S 0 1.0 2:13.63 Xorg 6820 ian 20 0 506m 83m 26m S 3 2.1 0:51.28 firefox 2004 ian 20 0 436m 23m 15m S 0 0.6 0:01.55 nautilus 2031 ian 20 0 419m 13m 10m S 0 0.3 0:00.11 evolution-alarm 2118 ian 20 0 372m 10m 7856 S 0 0.3 0:00.06 evolution-data- 2122 ian 20 0 344m 13m 10m S 0 0.3 0:00.10 evolution-excha 2001 ian 20 0 331m 22m 14m S 0 0.6 0:13.61 gnome-panel 1971 ian 20 0 299m 9.9m 7244 S 0 0.3 0:05.00 gnome-settings- 1989 ian 20 0 288m 15m 11m S 0 0.4 0:11.95 metacity 1954 ian 20 0 265m 5460 3412 S 0 0.1 0:00.28 pulseaudio
现在,让我们看一下 Linux 信号,它是一种与进程通信的异步方式。我们已经提到 SIGHUP 信号并且使用了 Ctrl-c 和 Ctrl-z 组合键,它们是向进程发送信号的其他方式。发送信号的常见方式是使用 kill 命令。
kill 命令将信号发送到指定的作业或进程。清单 22 显示使用 SIGTSTP 和 SIGCONT 信号来停止和恢复后台作业。使用 SIGTSTP 信号等效于使用 fg 命令将作业放到前台并使用 Ctrl-z 暂停它。使用 SIGCONT 类似于使用 bg 命令。
ian@attic4:~$ kill -s SIGTSTP %1 [1]+ Stopped xclock -d -update 1 ian@attic4:~$ jobs -l [1]+ 3878 Stopped xclock -d -update 1 [2] 5485 Running nohup sh pmc.sh & [3]- 5487 Running nohup bash pmc.sh & ian@attic4:~$ kill -s SIGCONT 3878 ian@attic4:~$ jobs -l [1] 3878 Running xclock -d -update 1 & [2]- 5485 Running nohup sh pmc.sh & [3]+ 5487 Running nohup bash pmc.sh &
在本例中,我们使用作业指示 (%1) 停止 xclock 进程,然后使用进程 ID(PID)重新启动(继续)它。如果您停止 job %2,然后使用 tail 及其后面的 -f 选项,您将看到仅有一个进程正在更新 nohup.out 文件。
您可以使用 kill -l 在系统中显示许多其他信号。其中一些信号用于报告错误,比如非法操作代码,浮点异常,或试图访问进程无权访问的内存。注意,信号也有编号(比如 20)和名称(比如 SIGTSTP)。您可以使用连字符 (-) 前面的编号,也可以使用 -s 选项和信号名。在我的系统中,我使用 kill -20,而不是 kill -s SIGTSTP。在确定哪个编号对应哪个信号之前,您应该检查系统中信号的编号。
您已经看到使用 Ctrl-c 可以终止进程。事实上,它向进程发送一个 SIGINT(或中断)信号。如果您使用不带任何信号名的 kill,它将发送一个 SIGTERM 信号。在大多数情况下,这两个信号是等效的。
您已经看到 nohup 命令可以让进程避开 SIGHUP 信号。一般情况下,进程可以实现一个信号处理程序 来捕捉 信号。因此进程可以实现信号处理程序来捕捉 SIGINT 或 SIGTERM。因为信号处理程序知道发送的信号是什么,所以它可能选择忽略 SIGINT,并且在收到(比如)SIGTERM 时才终止。清单 23 显示了如何将 SIGTERM 信号发送到 job %2。注意,在发送信号之后,进程状态立即显示为 “Terminated”。如果我们使用 SIGINT,将显示为 “Interrupt”。在片刻之后,将开始清除进程,作业也不再出现在作业列表中。
ian@attic4:~$ kill -s SIGTERM %2 ian@attic4:~$ [2]- Terminated nohup sh pmc.sh ian@attic4:~$ jobs -l [1]- 3878 Running xclock -d -update 1 & [3]+ 5487 Running nohup bash pmc.sh &
信号处理程序给进程提供了很大的灵活性。进程可以完成其常规工作,并且为了实现特定目的可以被信号中断。除了允许进程捕捉终止请求和采取可能的行动(比如关闭正在进行的文件或检查点事务)之外,信号还通常用于告诉守护进程重新读取其配置文件和重启操作。您在添加新的打印程序时可能要更改网络参数或 line printer daemon (lpd),这时可能需要进行该操作。
有一些信号是无法捕获的,比如某些硬件异常。您最常用的 SIGKILL 就不能被信号处理程序捕捉到,因此需要无条件终止它。总而言之,仅当所有办法都无法终止进程时,才选择无条件终止它。
还记得吗,使用 nohup 允许您在注销之后仍然让进程继续运行。让我们先注销然后再次登录。在登录之后,使用 jobs 和 ps 检查仍然在运行的简易时钟进程,和前面所做的一样。该操作的输出如清单 24 所示。
ian@attic4:~$ jobs -l ian@attic4:~$ ps -a PID TTY TIME CMD 10995 pts/0 00:00:00 ps
这次我们在 pts/0 中运行,但仅出现 ps 命令,而没有出现我们的作业。不过,它们并没有丢失。假设您不记得是否终止了使用 bash 启动的 nohup 作业或其他使用 bash 启动的作业。您在前面了解到如何找到运行 getty 命令的进程,因此您可以使用相同的方法来显示 SID、PID、PPID 和命令字符串。然后,您可以使用 -js 选项显示会话中的所有进程。清单 25 显示了结果。想想其他您曾用于找到这些进程的方法,比如搜索用户名然后使用 grep 进行过滤。
ian@attic4:~$ ps -C bash -C sh -o pid,sid,tname,cmd PID SID TTY CMD 5487 2643 ? bash pmc.sh 7050 7050 pts/3 -bash 10851 10851 pts/0 bash ian@attic4:~$ ps -js 2643 PID PGID SID TTY TIME CMD 5487 5487 2643 ? 00:00:00 bash 11197 5487 2643 ? 00:00:00 sleep
注意,pmc.sh 仍然运行,但现在控制 TTY 多了一个问号 (?)。
既然您现在已经学会了如何终止进程,您应该能够通过 PID 和 kill 命令终止仍然在运行的简易时钟进程。
Ian Shields 参与了 developerWorks Linux 专区的许多 Linux 项目。他是 IBM 北卡罗来纳州 Research Triangle Park 的一名高级程序员。他于 1973 年作为一名系统工程师加入 IBM 位于澳大利亚堪培拉的子公司。之后,在加拿大蒙特利尔和北卡罗莱那州 RTP 从事通信系统和普及运算。他拥有多项专利。他毕业于 Australian National University,本科学位是纯粹数学和哲学。他拥有北卡罗来纳州立大学的计算机硕士和博士学位。
Ian 是我们最受欢迎并且很多产的作者之一。查看 Ian 的个人资料 并与他和 My developerWorks 上的其他作者和读者联系。
http://www.ibm.com/developerworks/cn/linux/l-lpic1-v3-103-5/index.html
发布日期:2010 年 3 月 09 日
级别:中级
其他语言版本:英文