当程序运行在系统上时,我们称之为进程(process)。想要监测这些进程,需要熟悉ps命令的用法。ps命令好比工具中的瑞士军刀,它能输出运行在系统上的所有程序的许多信息。
但是随着ps命令的稳健而来的还有复杂性--有数不清的参数,这或许让ps命令成了最难掌握的命令。大多数系统管理员在掌握了能提供他们需要信息的一组参数后,就一直坚持只使用这组参数。
默认情况下,ps命令并不会提供那么多的信息:
1 xiaoyu@ubuntu:~$ ps
2 PID TTY TIME CMD
3 2051 pts/18 00:00:00 bash
4 2162 pts/18 00:00:00 ps
5 xiaoyu@ubuntu:~$
默认情况下,ps命令只会显示运行在当前控制台下的属于当前用户的进程,在此例中,我们只运行了bash shell(shell也只是运行在系统上的另一个程序而已)以及ps命令本身。
上例中的基本输出显示了程序的进程ID(Process ID, PID)、它们运行在哪个终端(TTY)以及进程已用的CPU时间。
Linux系统中使用的GNU ps命令支持3种不同类型的命令行参数:
Unix风格的参数是从贝尔实验室开发的AT&T Unix系统上原有的ps命令继承下来的,这些参数如下表所示
参数 | m描述 |
-A
|
显示所有进程
|
-N
|
显示与指定参数不符的所有进程 |
-a | 显示除控制进程(session leader)和无终端进程外的所有进程 |
-d | 显示除控制进程外的所有进程 |
-e | 显示所有进程 |
-C cmdlist | 显示包含在cmdlist列表中的进程 |
-G grplist | 显示组ID在grplist列表中的进程 |
-U userlist | 显示属主的用户ID在userlist列表中的进程 |
-g grplist | 显示会话或组ID在grplist列表中的进程 |
-p pidlist | 显示PID在pidlist列表中的进程 |
-s sesslist | 显示会话ID在sesslist列表中的进程 |
-t ttylist | 显示终端ID在ttylist列表中的进程 |
-u userlist | 显示有效用户ID在userlist列表中的进程 |
-F | 显示更多额外输出(相对-f参数而言) |
-O format | 显示默认的输出列以及format列表指定的特定列 |
-M | 显示进程的安全信息 |
-c | 显示进程的额外调度器信息 |
-f | 显示完整格式的输出 |
-j | 显示任务信息 |
-l | 显示长列表 |
-o format | 仅显示由format指定的列 |
-y | 不要显示进程标记(process flag,表明进程状态的标记) |
-Z | 显示安全标签(security context)①信息 |
-H | 用层级格式来显示进程(树状,用来显示父进程) |
-n namelist | 定义了WCHAN列显示的值 |
-w | 采用宽输出模式,不限宽度显示 |
-L | 显示进程中的线程 |
-V | 显示ps命令的版本号 |
上面给出的参数已经很多了,不过还有很多。使用ps命令的关键不在于记住所有可用的参数,而在于记住最有用的那些参数。大多数Linux系统管理员都有自己的一组参数,他们会牢牢记住这些用来提取有用的进程信息的参数。举个例子,如果你想查看系统上运行的所有进程,可用-ef参数组合(ps命令允许你像这样把参数组合在一起)。
1 xiaoyu@ubuntu:~$ ps -ef
2 UID PID PPID C STIME TTY TIME CMD
3 root 1 0 0 05:25 ? 00:00:02 /sbin/init auto noprompt
4 root 2 0 0 05:25 ? 00:00:00 [kthreadd]
5 root 4 2 0 05:25 ? 00:00:00 [kworker/0:0H]
6 root 6 2 0 05:25 ? 00:00:00 [mm_percpu_wq]
7 root 7 2 0 05:25 ? 00:00:00 [ksoftirqd/0]
8 root 8 2 0 05:25 ? 00:00:00 [rcu_sched]
9 root 9 2 0 05:25 ? 00:00:00 [rcu_bh]
10 root 10 2 0 05:25 ? 00:00:00 [migration/0]
11 root 11 2 0 05:25 ? 00:00:00 [watchdog/0]
12 root 12 2 0 05:25 ? 00:00:00 [cpuhp/0]
截取一段,Linux系统上运行着很多进程。这个例子用了两个参数:-e参数指定显示所有运行在系统上的进程;-f参数则扩展了输出,这些扩展的列包含了有用的信息。
上例子中输出了合理数量的信息,这也正是大多数系统管理员希望看到的。如果想要获得更多的信息,可采用-l参数,他会产生一个长格式输出。
1 xiaoyu@ubuntu:~$ ps -l
2 F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD
3 0 S 1000 2051 2045 0 80 0 - 7373 wait pts/18 00:00:00 bash
4 0 R 1000 2249 2051 0 80 0 - 8996 - pts/18 00:00:00 ps
5 xiaoyu@ubuntu:~$
注意使用了-l参数之后多出的那些列。
参数 | 描述 |
T | 显示跟当前终端关联的所有进程 |
a | 显示跟任意终端关联的所有进程 |
g | 显示所有的进程,包括控制进程 |
r | 仅显示运行中的进程 |
x | 显示所有的进程,甚至包括未分配任何终端的进程 |
U userlist | 显示归userlist列表中某用户ID所有的进程 |
p pidlist | 显示PID在pidlist列表中的进程 |
t ttylist | 显示所关联的终端在ttylist列表中的进程 |
O format | 除了默认输出的列之外,还输出由format指定的列 |
X | 按过去的Linux i386寄存器格式显示 |
Z | 将安全信息添加到输出中 |
j | 显示任务信息 |
l | 采用长模式 |
o format | 仅显示由format指定的列 |
s | 采用信号格式显示 |
u | 采用基于用户的格式显示 |
v | 采用虚拟内存格式显示 |
N namelist | 定义在WCHAN列中使用的值 |
O order | 定义显示信息列的顺序 |
S | 将数值信息从子进程加到父进程上,比如CPU和内存的使用情况 |
c | 显示真实的命令名称(用以启动进程的程序名称) |
e | 显示命令使用的环境变量 |
f | 用分层格式来显示进程,表明哪些进程启动了哪些进程 |
h | 不显示头信息 |
k sort | 指定用以将输出排序的列 |
n | 和WCHAN信息一起显示出来,用数值来表示用户ID和组ID |
w | 为较宽屏幕显示宽输出 |
H | 将线程按进程来显示 |
m | 在进程后显示线程 |
L | 列出所有格式指定符 |
V | 显示ps命令的版本号 |
如你所见,Unix和BSD类型的参数有很多重叠的地方。使用其中某种类型参数得到的信息也同样可以使用另一种获得。大多数情况下,你只要选择自己所喜欢格式的参数类型就行了(比如你在使用Linux之前就已经习惯BSD环境了)。在使用BSD参数时,ps命令会自动改变输出以模仿BSD格式。下例是使用l参数的输出:
1 xiaoyu@ubuntu:~$ ps l
2 F UID PID PPID PRI NI VSZ RSS WCHAN STAT TTY TIME COMMAND
3 0 1000 2051 2045 20 0 29492 4936 wait Ss pts/18 0:00 bash
4 0 1000 2354 2051 20 0 35984 1496 - R+ pts/18 0:00 ps l
5 xiaoyu@ubuntu:~$
注意,其中大部分的输出列跟使用Unix风格参数时的输出是一样的,只有一小部分不同。
许多系统管理员都喜欢BSD风格的l参数。它能输出更详细的进程状态码(STAT列)。双字符状态码能比Unix风格输出的单字符状态码更清楚地表示进程的当前状态。
第一个字符采用了和Unix风格S列相同的值,表明进程是在休眠、运行还是等待。第二个参数进一步说明进程的状态。
从前面的例子可以看出,bash命令处于休眠状态,但同时它也是一个控制进程(在我的会话中,它是主要进程),而ps命令则运行在系统的前台。
最后,GNU开发人员在这个新改进过的ps命令中加入了另外一些参数。其中一些GNU长参数复制了现有的Unix或BSD类型的参数,而另一些则提供了新功能。下表列出了现有的GNU长参数。
参数 | 描述 |
--deselect | 显示所有进程,命令行中列出的进程 |
--Group grplist | 显示组ID在grplist列表中的进程 |
--User userlist | 显示用户ID在userlist列表中的进程 |
--group grplist | 显示有效组ID在grplist列表中的进程 |
--pid pidlist | 显示PID在pidlist列表中的进程 |
--ppid pidlist | 显示父PID在pidlist列表中的进程 |
--sid sidlist | 显示会话ID在sidlist列表中的进程 |
--tty ttylist | 显示终端设备号在ttylist列表中的进程 |
--user userlist | 显示有效用户ID在userlist列表中的进程 |
--format format | 仅显示由format指定的列 |
--context | 显示额外的安全信息 |
--cols n | 将屏幕宽度设置为n列 |
--columns n | 将屏幕宽度设置为n列 |
--cumulative | 包含已停止的子进程的信息 |
--forest | 用层级结构显示出进程和父进程之间的关系 |
--headers | 在每页输出中都显示列的头 |
--no-headers | 不显示列的头 |
--lines n | 将屏幕高度设为n行 |
--rows n | 将屏幕高度设为n排 |
--sort order | 指定将输出按哪列排序 |
--width n | 将屏幕宽度设为n列 |
--help | 显示帮助信息 |
--info | 显示调试信息 |
--version | 示ps命令的版本号 |
1 xiaoyu@ubuntu:~$ ps --forest
2 PID TTY TIME CMD
3 2051 pts/18 00:00:00 bash
4 43622 pts/18 00:00:00 \_ ps
5 xiaoyu@ubuntu:~$
ps命令虽然在收集运行在系统上的进程信息时非常有用,但也有不足之处:它只能显示某个特定时间点的信息。如果想观察那些频繁换进换出的内存的进程趋势,用ps命令就不方便了。
而top命令刚好适用这种情况。top命令跟ps命令相似,能够显示进程信息,但它是实时显示的,下图是top命令运行时输出的截图
第二行显示了进程概要信息——top命令的输出中将进程叫作任务(task):有多少进程处在运行、休眠、停止或是僵化状态(僵化状态是指进程完成了,但父进程没有响应)。
下一行显示了CPU的概要信息。top根据进程的属主(用户还是系统)和进程的状态(运行、空闲还是等待)将CPU利用率分成几类输出。
作为系统管理员,很重要的一个技能就是知道何时以及如何结束一个进程。有时进程挂起了,只需要动动手让进程重新运行或结束就行了。但有时,有的进程会耗尽CPU且不释放资源。在这两种情景下,你就需要能控制进程的命令。Linux沿用了Unix进行进程间通信的方法。
在Linux中,进程之间通过信号来通信。进程的信号就是预定义好的一个消息,进程能识别它并决定忽略还是作出反应。进程如何处理信号是由开发人员通过编程来决定的。大多数编写完善的程序都能接收和处理标准Unix进程信号。这些信号都列在了下表中。
信号 | 名称 | 描述 |
1 | HUP | 挂机 |
2 | INT | 中断 |
3 | QUIT | 结束运行 |
9 | KILL | 无条件终止 |
11 | SEGV | 段错误 |
15 | TERM | 尽可能终止 |
17 | STOP | 无条件停止运行,但不终止 |
18 | TSTP | 停止或暂停,但继续在后台运行 |
19 | CONT | 在STOP或TSTP之后恢复执行 |
在Linux中有两个命令可以向运行中的进程发出进程信号。
kill命令可通过进程ID(PID)给进程发信号。默认情况下,kill命令会向命令行中列出的全部PID发送一个TERM信号,遗憾的是,你只能用进程的PID而不能用命令名,所以kill命令有时并不好用。
要发送进程信号,你必须是进程的属主或登陆为root用户。
1 xiaoyu@ubuntu:~$ kill 6447
2 bash: kill: (6447) - Operation not permitted
3 xiaoyu@ubuntu:~$
TERM信号告诉进程可能的话就停止运行。不过,如果有不服管教的进程,那它通常会忽略这个请求。如果要强制终止,-s参数支持制定其他信号(用信号名或信号值)。
从下例中看出,kill命令不会有任何输出。
1 xiaoyu@ubuntu:~$ kill 2120
2 xiaoyu@ubuntu:~$
要检查kill命令是否有效,可再运行ps或top命令,看看问题进程是否已停止。
killall命令非常强大,它支持通过进程名而不是PID来结束进程。killall命令也支持通配符,这在系统因负载过大而变得很慢时很有用。
1 xiaoyu@ubuntu:~$ killall http*
2 http*: no process found
3 xiaoyu@ubuntu:~$
嗯,我这台机器没有启动任何http的进程,不过这个命令大家是可以尝试使用的
原文:https://www.cnblogs.com/Reverse-xiaoyu/p/12070813.html