Linux任务控制

678 查看

这篇文章翻译自: http://linuxcommand.org/lts0080.php

上一课我们看到了Linux作为一个多用户系统的复杂之处(权限), 这一课我们来学习Linux的多任务特性和在命令行界面的操作方法.

如任何多任务系统一样, Linux执行的是多个同步的进程. 好吧, 它们只是看上去同步罢了. 实际上, 一个单处理器电脑在同一时间只能运行一个进程, 但Linux内核想办法给每个进程都有时间片轮流执行, 这样看上去它们就是同步的了.

我们有几个控制进程的命令:

  • ps - 把进程系统的列出 (注: 只有ps -A能列出系统所有进程, ps只能列出当前进程和它的子进程)
  • kill - 发送一个信号给进程 (通常用作杀进程)
  • jobs - 另一种方法, 列出你的进程
  • bg - 将一个进程放到后台执行
  • fg - 讲一个进程拉到前台执行

实际例子

虽说这个话题有那么点低级, 但是对于那些长期用图形界面的普通用户来说是很有实际意义的. 你可能不知道, 大多(即便不是所有)图形界面程序都能在命令行启动. 例如, 有一个带有X Windows系统的小程序xload, 它能显示一张图形以代表系统启动. 你可以键入下面这些来启动它:

shell[me@linuxbox me]$ xload

请留意到xload窗口出现并且显示了图形, 同时也该留意到提示符在程序启动之后不再出现. shell在等待(wait())程序完结, 然后才把控制权交还给你. 如果你关掉xload窗口, xload
程序终止, 提示符重新出现.

把程序放到后台

好, 为了改善生活, 我们要重新启动xload, 不过这次我们把它放到后台, 这样提示符就会回来了. 要做到这一点, 这样执行就好:

shell[me@linuxbox me]$ xload &
[1] 1223

[me@linuxbox me]$

在这个例子中, 提示符返回了, 因为程序被放到了后台.

现在想象一下你在执行一个后台的程序时, 把&符号打漏了. DON'T PANIC, 还是有希望的. 你先按下 Control-Z, 这样程序挂起. 程序还是在的, 只不过被闲置着. 要想在后台恢复它的运行, 运行bg (background的缩写):

shell[me@linuxbox me]$ xload
[2]+ Stopped xload

[me@linuxbox me]$ bg
[2]+ xload &

列出你的进程

现在我们把一个进程放到了后台, 这样列出我们启动了的进程就变得相当有用. 我们可以用jobs或者ps来完成这一点:

shell[me@linuxbox me]$ jobs
[1]+ Running xload &

[me@linuxbox me]$ ps
PID TTY TIME CMD
1211 pts/4 00:00:00 shell
1246 pts/4 00:00:00 xload
1247 pts/4 00:00:00 ps

[me@linuxbox me]$

人被杀, 就会死

设想有个程序无响应了(hmmm...Netscape浮现在脑中 ;-); 怎么把它弄走? 当然, 你可以用kill命令. 我们来在xload上试试刀. 首先你得得到那个将被杀的程序的标识. 你可以用ps或者jobs, 用jobs得到job号, 用ps得到进程id (PID). 我们两个都试一下:

shell[me@linuxbox me]$ xload &
[1] 1292

[me@linuxbox me]$ jobs
[1]+ Running xload &

[me@linuxbox me]$ kill %1

[me@linuxbox me]$ xload &
[2] 1293
[1] Terminated xload

[me@linuxbox me]$ ps
PID TTY TIME CMD
1280 pts/5 00:00:00 shell
1293 pts/5 00:00:00 xload
1294 pts/5 00:00:00 ps

[me@linuxbox me]$ kill 1293
[2]+ Terminated xload

[me@linuxbox me]$

就算是神, 我也杀给你看! (误

"kill"命令通常用作杀进程, 而它的的作用其实是向进程发送一个信号. 大多数时候信号就是告诉程序"好了别再运行了", 然后没有然后了. 程序监听和回应操作系统信号(如果它们写得好), 大多数时候都是为了能有一个更优雅的终止方式(死法). 例如, 一个文本编辑器可能要监听用户是不是要登出, 或者电脑是不是要关机. 当它收到这些信号, 它就得在退出之前保存工作. kill命令能法送一大堆不同的信号呢, 键入:

shellkill -l

就会列出它支持的信号. 大多都比较晦涩, 不过有几个是蛮常用:

信号

Num Name Description
1 SIGHUP 挂起信号. 程序可以监听并决定是否挂起(注: 见nohup命令和Control-Z)
2 SIGINT 中断信号. 这个信号希望让进程中断的, 当然最终的行为由进程自己决定. 你可以在终端按Control-C(aka, 键盘中断)来发出这个信号.
15 SIGTERM 终止信号. 这个信号希望让进程终止的, 最终的行为仍由进程自己决定. 这是kill命令默认发出的信号.
9 SIGKILL 杀信号. 这个信号用于立即终止进程. 它由内核发出, 无法监听和处理.

好现在设想你有一个进程已经毫无希望地卡在那里了(比如可怜地Netscape), 你要停掉它, 你该这样做:

  • 用ps命令获取它地进程号 (PID).
  • 对这个 PID 执行kill.
  • 如果进程拒绝终止(比如它忽略了这个信号), 那么就对它发出更加严厉的信号, 直到它停止了.
shell[me@linuxbox me]$ ps x
PID TTY STAT TIME COMMAND
2931 pts/5 SN 0:00 netscape
[me@linuxbox me]$ kill -SIGTERM 2931
[me@linuxbox me]$ kill -SIGKILL 2931

这个例子中, 我以一个更加形式化的写法来用kill命令. 在实际应用中, 下面这个更常用, 因为kill默认发出SIGTERM, -信号也可以用数字而不是名字来代替:

shell[me@linuxbox me]$ kill 2931

如果进程还不终止, 那就用SIGKILL强制终止:

shell[me@linuxbox me]$ kill -9 2931

原来如此!

这在"Learning the shell"系列课程中的最后一个. 下一个系列, "写shell脚本", 我们将学习如何用shell脚本自动化任务.