ps

管理进程的第一步是找出当前正在运行的进程。最常用最强大的工具是 ps(1) 。没有任何参数时,ps 不会告诉你太多信息。默认情况下,它仅仅会告诉你当前激活的终端里正在运行的进程。如果你想要更多信息,我们需要更加深入。

darkstar:~$ ps
  PID TTY          TIME CMD
12220 pts/4    00:00:00 bash
12236 pts/4    00:00:00 ps

你可以看到当前终端下所有运行的程序,而且只包括一部分信息。 PID 是进程 ID;每一个进程都被标识了一个唯一的数字。 TTY 告诉你进程所连接的终端。 CMD 是运行的命令。你可能会对 TIME 有点困惑,因为它看起来变得太慢。这并不是进程已经运行的时间,而是进程消耗的CPU 时间。事实上空闲进程不使用 CPU 时间,所以这个值不会增长得太快。

只看我们自己的进程没什么意思,所以让我们用 -e 参数查看系统上所有的进程。

darkstar:~$ ps -e
  PID TTY          TIME CMD
    1 ?        00:00:00 init
    2 ?        00:00:00 kthreadd
    3 ?        00:00:00 migration/0
    4 ?        00:00:00 ksoftirqd/0
    7 ?        00:00:11 events/0
    9 ?        00:00:01 work_on_cpu/0
   11 ?        00:00:00 khelper
  102 ?        00:00:02 kblockd/0
  105 ?        00:01:19 kacpid
  106 ?        00:00:01 kacpi_notify
... many more lines omitted ...

上面的例子使用了标准的 ps 语法,但是如果使用 BSD 语法会发现更多信息。我们可以使用 aux 参数达成目的。

注意

这与 -aux 参数是不同的,但是大多数情况下两者是等价的。这是很老的遗留问题。更多信息可以参考 ps 的 man 页面。

darkstar:~$ ps aux
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.0  0.0   3928   632 ?        Ss   Apr05   0:00 init [3]
root         2  0.0  0.0      0     0 ?        S    Apr05   0:00 [kthreadd]
root         3  0.0  0.0      0     0 ?        S    Apr05   0:00 [migration/0]
root         4  0.0  0.0      0     0 ?        S    Apr05   0:00 [ksoftirqd/0]
root         7  0.0  0.0      0     0 ?        S    Apr05   0:11 [events/0]
root         9  0.0  0.0      0     0 ?        S    Apr05   0:01 [work_on_cpu/0]
root        11  0.0  0.0      0     0 ?        S    Apr05   0:00 [khelper]
... many more lines omitted ....

可以看到,BSD 语法提供了更多的信息,包括哪个用户在控制进程以及当运行 ps 时进程的内存和 CPU 占用率。

为了完成这些,ps 允许在进程的基础上提供一个或多个进程 PID 作为参数,且使用 -o 参数显示这些进程的特定属性。

darkstar:~$ ps -o cmd -o etime $$
CMD                             ELAPSED
/bin/bash                         12:22

这里显示的是进程的命令名称(cmd),和它的消逝的时间(etime)。这个例子中的 PID,是一个 shell 变量,是当前 shell 的 PID。所以你可以看到,在这个例子中,shell 进程存活了 12 分钟 22 秒。

使用 pgrep(1) 命令,可以更自动化的得到这些信息。

darkstar:~$ ps -o cmd -o rss -o vsz $(pgrep httpd)
CMD                           RSS    VSZ
/usr/sbin/httpd -k restart  33456  84816
/usr/sbin/httpd -k restart  33460  84716
/usr/sbin/httpd -k restart  33588  84472
/usr/sbin/httpd -k restart  30424  81608
/usr/sbin/httpd -k restart  33104  84900
/usr/sbin/httpd -k restart  33268  85112
/usr/sbin/httpd -k restart  30640  82724
/usr/sbin/httpd -k restart  15168  67396
/usr/sbin/httpd -k restart  33180  84416
/usr/sbin/httpd -k restart  33396  84592
/usr/sbin/httpd -k restart  32804  84232

在这个例子中,使用 grep 的子语句返回命令名包含 httpd 的所有进程。然后 ps 显示命令名,常驻内存大小和虚拟内存大小。

最后,ps 也可以创建进程树。这可以显示哪些进程有子进程。结束一个子进程的父进程也会结束这个子进程。我们可以使用 -ejH 参数做这些。

darkstar:~$ ps -ejH
... many lines omitted ...
 3660  3660  3660 tty1     00:00:00   bash
29947 29947  3660 tty1     00:00:00     startx
29963 29947  3660 tty1     00:00:00       xinit
29964 29964 29964 tty7     00:27:11         X
29972 29972  3660 tty1     00:00:00         sh
29977 29972  3660 tty1     00:00:05           xscreensaver
29988 29972  3660 tty1     00:00:04           xfce4-session
29997 29972  3660 tty1     00:00:16             xfwm4
29999 29972  3660 tty1     00:00:02             Thunar
... many more lines omitted ...

你可以看到,ps(1) 是很强大的工具,不仅仅能查看正在运行的进程,也能获取它们的一些重要的信息。

正如许多应用的情况,通常提供了一些工具做这项工作。与 ps -ehH 的输出相似,但是更精炼的是 pstree(1) 。它更形象化地显示进程树。

darkstar:~$ pstree
init-+-atd
     |-crond
     |-dbus-daemon
     |-httpd---10*[httpd]
     |-inetd
     |-klogd
     |-mysqld_safe---mysqld---8*[{mysqld}]
     |-screen-+-4*[bash]
     |        |-bash---pstree
     |        |-2*[bash---ssh]
     |        `-bash---irssi
     |-2*[sendmail]
     |-ssh-agent
     |-sshd---sshd---sshd---bash---screen
     `-syslogd

最后更新于