• CentOS 7上的进程管理


    一些杂乱的基础概念

    程序是一种静态的文件,躺在磁盘上。而进程则是将程序运行起来放置于内存中。因此进程就是运行中的程序,是程序运行起来的一个实例。同一个程序可以运行为多个进程/实例。

    进程之间有父子关系,即父进程与子进程之间的关系。父进程结束后,子进程也会随之结束。因此,当我们通过终端连接上之后,随即启用了一个与终端相关的shell进程(如bash),我们在该终端中运行的任何程序,都是这个终端的子进程。因此当我们在终端中运行一个需要长时间执行的程序,还未运行完毕便退出终端的话,那么该长时间运行的程序也会自动结束掉的。

    进程一般通过一些系统调用来创建,例如进程通过fork()或者clone()来复制自身创建新进程。

    CentOS 6上最上层的进程是init进程,CentOS 7上最上层的进程是systemd进程。在一些情况下,父进程结束后,子进程还会存在,这类子进程被称为孤儿进程(orphan process),它们会被init/systemd进程所“收养”。

    进程有优先级的概念,优先级越低的进程可以享受越多的CPU资源。无法直接调整进程的优先级,只能通过调整进程的nice值来改变,nice值越高进程优先级越高(优先级高越不优先)。可以理解为越高的nice值表示进程更愿意占用更少的CPU资源。普通用户只可以调高自身进程的nice值,只有root用户才可以随意调整nice值。

    关于内存的一些基本概念,例如物理内存、虚拟内存、内存分页和多级分页表,推荐阅读【Linux的内存分页管理 - Vamei - 博客园】

    进程间通信

    • 主机内部。
      • signal(信号)。
      • shm(SHared Memory,共享内存)。
      • semaphore(信号量)。
    • 主机之间。
      • RPC(Remote Procedure Call,远程过程调用)。
      • socket。

    进程类型

    守护进程(daemon):一般是作为服务类的进程运行于系统后台,与终端无关。一般是随系统启动的时候启动,也可以在系统启动后在终端手动启动,启动后会自动进入系统后台。例如常见的httpd、nginx和mysqld等服务。

    前台进程:运行与前台的进程,与终端相关,如果需要一段运行时间的话,会占用终端。例如我们基于php-cli工具手工运行一些php脚本。

    进程根据占用资源的类型还可以分为CPU密集型(CPU-Bound)和IO密集型(IO-Bound)。

    进程状态

    • 运行态:running。
    • 就绪态:ready。
    • 睡眠态:分为两种,可中断(interruptable)睡眠和不可中断(uninterruptable)睡眠。不可中断的睡眠一般是由于进程在等待IO处理。
    • 停止态:stopped,处于内存中停止的状态,不会占用CPU资源,除非手动启动。
    • 僵死态:zombie,类似进程卡死吧,是一种不好的状态。

    init进程

    在Linux系统中,操作系统在启动过程中如何一步步启动进程,系统如何管理进程与服务,这些都与一个初始化进程相关,那就是init进程。它一般是OS中最先启动的进程,一般PID为0。在不同的CentOS版本中其对应的init进程不一样。

    目前大多数主流的Linux发行版采用Systemd方案。

    命令

    pstree

    pstree用于以树状的形式显示当前的进程。

    [root@C7 ~]# pstree
    systemd─┬─ModemManager───2*[{ModemManager}]
            ├─NetworkManager─┬─dhclient
            │                └─2*[{NetworkManager}]
            ├─VGAuthService
            ├─2*[abrt-watch-log]
            ├─abrtd
            ├─accounts-daemon───2*[{accounts-daemon}]
            ├─alsactl
            ├─at-spi-bus-laun─┬─dbus-daemon
            │                 └─3*[{at-spi-bus-laun}]
            ├─at-spi2-registr───2*[{at-spi2-registr}]
            ├─atd
            ├─auditd─┬─audispd─┬─sedispatch
            │        │         └─{audispd}
            │        └─{auditd}
            ├─avahi-daemon───avahi-daemon
            ├─bluetoothd
            ├─colord───2*[{colord}]
            ├─crond
            ├─cupsd
            ├─2*[dbus-daemon]
            ├─dbus-launch
            ├─dnsmasq───dnsmasq
            ├─firewalld───{firewalld}
            ├─gdm─┬─X───5*[{X}]
            │     ├─gdm-session-wor─┬─gnome-session-b─┬─gnome-shell─┬─ibus-daemon─┬─ibus-dconf───3*[{ibus-dconf}]
            │     │                 │                 │             │             ├─ibus-engine-sim───2*[{ibus-engine-sim}]
            │     │                 │                 │             │             └─2*[{ibus-daemon}]
            │     │                 │                 │             └─20*[{gnome-shell}]
            │     │                 │                 ├─gsd-a11y-keyboa───3*[{gsd-a11y-keyboa}]
            │     │                 │                 ├─gsd-a11y-settin───3*[{gsd-a11y-settin}]
            │     │                 │                 ├─gsd-clipboard───2*[{gsd-clipboard}]
            │     │                 │                 ├─gsd-color───3*[{gsd-color}]
            │     │                 │                 ├─gsd-datetime───2*[{gsd-datetime}]
            │     │                 │                 ├─gsd-housekeepin───2*[{gsd-housekeepin}]
            │     │                 │                 ├─gsd-keyboard───3*[{gsd-keyboard}]
            │     │                 │                 ├─gsd-media-keys───3*[{gsd-media-keys}]
            │     │                 │                 ├─gsd-mouse───2*[{gsd-mouse}]
            │     │                 │                 ├─gsd-power───3*[{gsd-power}]
            │     │                 │                 ├─gsd-print-notif───2*[{gsd-print-notif}]
            │     │                 │                 ├─gsd-rfkill───2*[{gsd-rfkill}]
            │     │                 │                 ├─gsd-screensaver───2*[{gsd-screensaver}]
            │     │                 │                 ├─gsd-sharing───3*[{gsd-sharing}]
            │     │                 │                 ├─gsd-smartcard───4*[{gsd-smartcard}]
            │     │                 │                 ├─gsd-sound───3*[{gsd-sound}]
            │     │                 │                 ├─gsd-wacom───2*[{gsd-wacom}]
            │     │                 │                 ├─gsd-xsettings───3*[{gsd-xsettings}]
            │     │                 │                 └─3*[{gnome-session-b}]
            │     │                 └─2*[{gdm-session-wor}]
            │     └─3*[{gdm}]
            ├─gssproxy───5*[{gssproxy}]
            ├─ibus-portal───2*[{ibus-portal}]
            ├─ibus-x11───2*[{ibus-x11}]
            ├─irqbalance
            ├─ksmtuned───sleep
            ├─libvirtd───16*[{libvirtd}]
            ├─lsmd
            ├─lvmetad
            ├─master─┬─pickup
            │        └─qmgr
            ├─packagekitd───2*[{packagekitd}]
            ├─polkitd───5*[{polkitd}]
            ├─pulseaudio───2*[{pulseaudio}]
            ├─rngd
            ├─rpcbind
            ├─rsyslogd───2*[{rsyslogd}]
            ├─rtkit-daemon───2*[{rtkit-daemon}]
            ├─smartd
            ├─sshd─┬─sshd───bash───man───less
            │      └─sshd───bash───pstree
            ├─systemd-journal
            ├─systemd-logind
            ├─systemd-udevd
            ├─tuned───4*[{tuned}]
            ├─udisksd───4*[{udisksd}]
            ├─upowerd───2*[{upowerd}]
            ├─vmtoolsd───{vmtoolsd}
            ├─wpa_supplicant
            └─xdg-permission-───2*[{xdg-permission-}]

    对于相同的子进程,pstree会将其折叠,并使用数字显示其相同子进程数。例如。

    init-+-getty
          |-getty
          |-getty
          `-getty

    会被折叠成。

    init---4*[getty]

    子进程的折叠显示使用的是方括号,而子线程的折叠显示使用了方括号与花括号。

    icecast2---13*[{icecast2}]

    -c:如果想要取消折叠(compact)功能的话,可使用该选项。

    -p:默认情况下,pstree不会显示PID,加上该选项可实现显示PID功能。该选项暗含了-c选项(禁用折叠)。

    知道了PID之后,pstree可加上PID参数,用来显示以某个PID为根的进程树。

    [root@C7 ~]# pstree -p 1214
    tuned(1214)─┬─{tuned}(1541)
                ├─{tuned}(1542)
                ├─{tuned}(1543)
                └─{tuned}(1558)

    -a:显示进程的命令行选项参数等。使用该选项有时会因为命令行参数太长而无法显全,可结合-l选项查看长格式。

      ├─dbus-daemon --fork --print-pid 5 --print-address 7 --session
      ├─dbus-daemon --system --address=systemd: --nofork --nopidfile --systemd-activation

    -h:高亮显示当前进程以及祖先进程。

    -H:高亮显示指定PID进程以及祖先进程。

    # pstree -H PID

    -g:显示进程的PGID(Process Group ID,进程组ID),我不懂什么是进程组,从结果来看,子进程和进程的子线程的PGID等同于父进程的PID。同时显示PID和PGID时,先显示PID后显示PGID。

    -s:显示进程的祖先进程。

    [root@C7 ~]# pstree -p 1541
    {tuned}(1541)
    [root@C7 ~]# pstree -sp 1541
    systemd(1)───tuned(1214)───{tuned}(1541)

    -u:显示进程的用户名(UID),如果有的话。知道用户名以后,用户名可作为命令参数来显示与该用户名相关的进程树。

    [root@C7 ~]# pstree -p postfix
    pickup(3311)
    
    qmgr(1401)

    ps

    ps命令用于显示当前系统上的进程信息,也叫做当前进程快照(snapshot)。

    它支持三种风格的选项:

    • UNIX风格,选项可以被合并并且只能有一个连接号(-)。在man手册中,UNIX风格,也叫做标准(standard)或者POSIX风格。
    • BSD风格,选项可以被合并并且不能有连接号(-)。
    • GNU长选项,必须有两个连接号(-)。

    由于ps有许多不同的版本,因此该版本(CentOS 7上的ps)为了兼容性考虑,会存在许多功能相同的选项。不同风格的选项可以混合使用,但是可能会产生冲突,因此建议不要混合使用。

    不同风格的选项名称(字符)可能相同但不代表含义相同,例如以下2个命令,意义就不一样。

    # ps aux
    # ps -aux

    虽然它们显示的结果是相同的,下文会解释。

    选项组合一:aux

    a:使ps列出所有和终端(tty)相关的进程,当和x选项共同使用的时候显示所有的进程。

    x:使ps列出所有和你(应该是当前的有效UID,Effective UID)相关的进程,当和x选项共同使用的时候显示所有的进程。

    u:以面向用户的格式输出。

    a和x选项属于简单进程选取(SIMPLE PROCESS SELECTION)类选项。

    u选项属于输出格式控制(OUTPUT FORMAT CONTROL)类选项。

    因此该组合的作用是:以面向用户的格式,BSD的风格显示系统上所有的进程信息。

    [root@C7 ~]# ps aux
    USER        PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
    root          1  0.2  0.4 191172  4168 ?        Ss   10:03   0:01 /usr/lib/systemd/systemd --switched-root --system --deserialize 22
    root          2  0.0  0.0      0     0 ?        S    10:03   0:00 [kthreadd]
    root          3  0.0  0.0      0     0 ?        S    10:03   0:00 [ksoftirqd/0]
    root          5  0.0  0.0      0     0 ?        S<   10:03   0:00 [kworker/0:0H]
    ...
    root        499  0.0  0.3  37376  3496 ?        Ss   10:03   0:00 /usr/lib/systemd/systemd-journald
    root        528  0.0  0.1 124792  1320 ?        Ss   10:03   0:00 /usr/sbin/lvmetad -f
    root        532  0.0  0.3  45648  3032 ?        Ss   10:03   0:00 /usr/lib/systemd/systemd-udevd
    ...
    root       1495  0.0  1.8 320832 18444 tty1     Ssl+ 10:03   0:00 /usr/bin/X :0 -background none -noreset -audit 4 -verbose -auth /run/gdm/auth-for-gdm-lKoaJ3/database -seat seat0 -nolist
    ...
    root       1949  0.0  0.3 116628  3256 pts/0    Ss   10:04   0:00 -bash
    root       1990  0.0  0.2 119788  2472 pts/0    S+   10:05   0:00 man ps
    root       2003  0.0  0.0 110336   980 pts/0    S+   10:05   0:00 less -s
    ...

    我们再来看一下ps -aux的含义。

    -a:选取除了会话首进程(session leader,相见getsid(2)的man手册)和与终端无关的进程以外的所有进程。

    -u:根据有效用户ID(EUID)来选取进程。其后接的就是用户名了。

    因此,“-aux”的含义即选取满足用户名为“x”和-a选项条件的进程,如果不存在用户x,那么其效果等同于“aux”,这也就是为什么在实际运行时,“ps aux”和“ps -aux”的结果是一样的了。

    接下来解释几个字段的含义。

    USER:进程所对应的用户。

    PID:进程ID。

    %CPU:进程所占用的CPU百分比,占用的CPU时间/进程所运行的时间(cputime/realtime)。

    %MEM:进程所占用的内存百分比。

    VSZ:虚拟内存的大小,单位是KB。设备映射当前不包含;这点可能会改变。

    RSS:Resident Size,常驻内存集,单位是KB。一个任务所使用到的非swap物理内存。

    TTY:与进程所关联的终端。

    STAT:进程状态。默认情况下,似乎进程的状态只有在BSD风格的选项下才会被显示。在UNIX风格的话,可能得通过-o来显示了,并且使用了-o,就不可以使用其他UNIX风格的输出格式控制了,例如-o和-f一起用是不行的。

    • R:running,运行态。
    • S:Interruptable Sleeping,可中断睡眠态。
    • D:Uninterruptable Sleeping,不可中断睡眠态。进程处于等待的时候,可以理解为睡眠,如果进程是等待网络或者磁盘的IO,这种一般是必须等待完毕才可以继续运行进程的,那么这种是不可中断的睡眠状态,反之则为可中断。
    • T:Stopped,停止态。进程通过Ctrl+z调入后台时处于该状态。
    • Z:Zombie,僵死态。进程等待被回收。
    • +:前台进程。
    • l:多线程进程。
    • N:低优先级进程。具备nice值,对其他进程nice,因此这里说的”优先级“就真的是越低越不优先了。
    • <:高优先级进程。
    • s:session leader,会话首进程。

    START:进程所启动的时间点。

    TIME:进程所占用的CPU时间。

    COMMAND:完整的命令行信息。

    选项组合二:-ef

    -e:选择所有的进程,等同于-A。

    -f:显示长格式详细信息。

    [root@C7 ~]# ps -ef 
    UID         PID   PPID  C STIME TTY          TIME CMD
    root          1      0  0 10:03 ?        00:00:02 /usr/lib/systemd/systemd --switched-root --system --deserialize 22
    root          2      0  0 10:03 ?        00:00:00 [kthreadd]
    root          3      2  0 10:03 ?        00:00:00 [ksoftirqd/0]
    root          5      2  0 10:03 ?        00:00:00 [kworker/0:0H]
    ...
    root        691      1  0 10:03 ?        00:00:00 /sbin/auditd
    root        693    691  0 10:03 ?        00:00:00 /sbin/audispd
    root        695    693  0 10:03 ?        00:00:00 /usr/sbin/sedispatch
    ...
    root       1495   1231  0 10:03 tty1     00:00:00 /usr/bin/X :0 -background none -noreset -audit 4 -verbose -auth /run/gdm/auth-for-gdm-lKoaJ3/database -seat seat0 -nolisten tcp vt1
    ...
    root       1949   1943  0 10:04 pts/0    00:00:00 -bash
    root       1990   1949  0 10:05 pts/0    00:00:00 man ps
    root       2003   1990  0 10:05 pts/0    00:00:00 less -s
    root       2017   1213  0 10:06 ?        00:00:00 sshd: root@pts/1
    root       2023   2017  0 10:06 pts/1    00:00:00 -bash
    ...

    UID:等同于ps aux输出中的USER,进程的用户。

    PPID:该进程的父进程ID。

    C:CPU的使用情况,等同于%CPU。

    CMD:等同于COMMAND。

    -f选项还可以结合其他的UNIX风格选项来增加额外的字段信息。例如结合-L选项。

    -L:显示线程信息,NLWP表示线程数量,LWP表示线程ID。LWP的英文全称是Light Weight Process,由此可见,线程即是轻量级的进程。

    [root@C7 ~]# ps -efL | head -n 1
    UID         PID   PPID    LWP  C NLWP STIME TTY          TIME CMD
    [root@C7 ~]# ps -ef | grep "auditd"
    root        109      2  0 10:03 ?        00:00:00 [kauditd]
    root        691      1  0 10:03 ?        00:00:00 /sbin/auditd
    root       6178   2023  0 15:41 pts/1    00:00:00 grep --color=auto auditd
    [root@C7 ~]# ps -efL | grep "auditd"
    root        109      2    109  0    1 10:03 ?        00:00:00 [kauditd]
    root        691      1    691  0    2 10:03 ?        00:00:00 /sbin/auditd
    root        691      1    692  0    2 10:03 ?        00:00:00 /sbin/auditd
    root       6180   2023   6180  0    1 15:41 pts/1    00:00:00 grep --color=auto auditd

    可见,原本/sbin/auditd只是一条进程信息,在显示线程信息后,它显示成了2条,PID相同,不过线程ID(LWP)不同。

    选项组合三:-eFH

    -F:基于-f选项,显示比起更详细的信息。

    -H:以进程树的格式显示。

    [root@C7 ~]# ps -eFH
    UID         PID   PPID  C    SZ   RSS PSR STIME TTY          TIME CMD
    root          2      0  0     0     0   0 10:03 ?        00:00:00 [kthreadd]
    root          3      2  0     0     0   0 10:03 ?        00:00:00   [ksoftirqd/0]
    root          5      2  0     0     0   0 10:03 ?        00:00:00   [kworker/0:0H]
    root          7      2  0     0     0   0 10:03 ?        00:00:00   [migration/0]
    root          8      2  0     0     0   0 10:03 ?        00:00:00   [rcu_bh]
    ...
    root          1      0  0 47793  4168   1 10:03 ?        00:00:02 /usr/lib/systemd/systemd --switched-root --system --deserialize 22
    root        499      1  0  9344  4028   0 10:03 ?        00:00:00   /usr/lib/systemd/systemd-journald
    root        528      1  0 31198  1320   2 10:03 ?        00:00:00   /usr/sbin/lvmetad -f
    root        532      1  0 11412  3032   1 10:03 ?        00:00:00   /usr/lib/systemd/systemd-udevd
    root        691      1  0 13877   900   2 10:03 ?        00:00:00   /sbin/auditd
    root        693    691  0 21138   936   0 10:03 ?        00:00:00     /sbin/audispd
    root        695    693  0 13899  1416   0 10:03 ?        00:00:00       /usr/sbin/sedispatch
    ...

    SZ:进程的core image的物理页(page)大小。包含文本、数据和栈空间(stack space)。设备映射当前不包含;这点可能会改变。

    PSR:进程目前在哪个CPU核心上运行。

    选项组合四:-eo,axo

    o, -o, --format:输出格式的一种格式,可以让用户自定义显示字段信息。字段信息是一个列表,以逗号或者空格分隔,一般以逗号。字段信息使用关键词(keyword)来表示,关键词除了可用于-o选项显示字段信息外,还可用于--sort选项来分类排序。例如。

    [root@C7 ~]# ps -eo pid,user,args --sort user | head
       PID USER     COMMAND
       731 avahi    avahi-daemon: running [C7.local]
       746 avahi    avahi-daemon: chroot helper
      1726 colord   /usr/libexec/colord
       744 dbus     /usr/bin/dbus-daemon --system --address=systemd: --nofork --nopidfile --systemd-activation
      1512 gdm      /usr/libexec/gnome-session-binary --autostart /usr/share/gdm/greeter/autostart
      1518 gdm      dbus-launch --exit-with-session /usr/libexec/gnome-session-binary --autostart /usr/share/gdm/greeter/autostart
      1519 gdm      /usr/bin/dbus-daemon --fork --print-pid 5 --print-address 7 --session
      1526 gdm      /usr/libexec/at-spi-bus-launcher
      1531 gdm      /bin/dbus-daemon --config-file=/usr/share/defaults/at-spi2/accessibility.conf --nofork --print-address 3

    字段名也可以置空或者根据需求重命名。如果全部置空的话,就不会显示首行字段名行了。

    [root@C7 ~]# ps -eo pid,user=,args=mingling --sort user | head -n 3
       PID          mingling
       731 avahi    avahi-daemon: running [C7.local]
       746 avahi    avahi-daemon: chroot helper

    字段的宽度会自动调节,也可以在字段名后面使用“:number”的形式来明确具体的宽度。

    [root@C7 ~]# ps -eo uid:5,pid:10,ppid:30
      UID        PID                           PPID
        0          1                              0
        0          2                              0
        0          3                              2
        0          5                              2
        0          7                              2
        0          8                              2
    ...

    当选项使用情况比较复杂的时候,可以使用多个-o选项。

    具体的字段关键词,在ps(1)的man手册中的STANDARD FORMAT SPECIFIERS中有描述。

           CODE        HEADER    DESCRIPTION
    
           %cpu        %CPU      cpu utilization of the process in "##.#" format.  Currently, it is the CPU time used divided by the
                                 time the process has been running (cputime/realtime ratio), expressed as a percentage.  It will not
                                 add up to 100% unless you are lucky.  (alias pcpu).
    
           %mem        %MEM      ratio of the process's resident set size  to the physical memory on the machine, expressed as a
                                 percentage.  (alias pmem).
    ... ...

    CODE:在CLI中需要输入的关键词。

    HEADER:在输出中显示的首行字段名称。

    DESCRIPTION:详细的描述信息。

    此前选项的输出信息,如果某些字段不明了,也是参考这部分的信息。

    基于列表选取进程

    上面所述的选项,在选取进程的时候,都是选择某一类进程。例如-e、ax选项可选取所有进程等等。

    除此之外还可基于列表,列表可以是用户列表或者PID列表。

    先来看基于用户列表。

    以不同的格式显示有效UID和真实UID为postfix的进程。

    -u:有效(effective)UID,即EUID。EUID用于文件访问权限的判断。

    -U:真实(real)UID,即RUID。RUID用户识别创建进程的用户。

    [root@C7 ~]# ps -u postfix -U postfix -f
    UID         PID   PPID  C STIME TTY          TIME CMD
    postfix    1378   1374  0 11:04 ?        00:00:00 qmgr -l -t unix -u
    postfix    3325   1374  0 12:44 ?        00:00:00 pickup -l -t unix -u
    [root@C7 ~]# ps -u postfix -U postfix -F
    UID         PID   PPID  C    SZ   RSS PSR STIME TTY          TIME CMD
    postfix    1378   1374  0 22968  4096   3 11:04 ?        00:00:00 qmgr -l -t unix -u
    postfix    3325   1374  0 22951  4088   0 12:44 ?        00:00:00 pickup -l -t unix -u
    [root@C7 ~]# ps -u postfix -U postfix u
    USER        PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
    postfix    1378  0.0  0.4  91872  4096 ?        S    11:04   0:00 qmgr -l -t unix -u
    postfix    3325  0.0  0.4  91804  4088 ?        S    12:44   0:00 pickup -l -t unix -u

    在这个示例中,我们也看到了不同风格选项的使用。并且为了避免ps程序感到疑惑,我们将选项分开书写,向下面这个例子,就是写在一起报错了。

    [root@C7 ~]# ps -uU postfix -F
    error: user name does not exist

    既然说是列表了,那么用户名也可以多个。

    [root@C7 ~]# ps -u postfix,colord,rtkit -f
    UID         PID   PPID  C STIME TTY          TIME CMD
    rtkit       732      1  0 11:04 ?        00:00:00 /usr/libexec/rtkit-daemon
    postfix    1378   1374  0 11:04 ?        00:00:00 qmgr -l -t unix -u
    colord     1727      1  0 11:04 ?        00:00:00 /usr/libexec/colord
    postfix    3325   1374  0 12:44 ?        00:00:00 pickup -l -t unix -u

    再来看进程列表。

    p PID_LIST
    -p PID_LIST
    --pid PID_LIST
    --ppid PID_LIST
    [root@C7 ~]# ps -p 732,1378,1727,3325 -f
    UID         PID   PPID  C STIME TTY          TIME CMD
    rtkit       732      1  0 11:04 ?        00:00:00 /usr/libexec/rtkit-daemon
    postfix    1378   1374  0 11:04 ?        00:00:00 qmgr -l -t unix -u
    colord     1727      1  0 11:04 ?        00:00:00 /usr/libexec/colord
    postfix    3325   1374  0 12:44 ?        00:00:00 pickup -l -t unix -u

    进程列表也可以只有一个PID,此情况下可以直接作为ps命令的参数。

    # ps PID
    # ps -PID

    这种适合于引用可返回PID的命令结果,例如pgrep。

    [root@C7 ~]# ps -p $(pgrep systemd)
       PID TTY      STAT   TIME COMMAND
         1 ?        Ss     0:02 /usr/lib/systemd/systemd --switched-root --system --deserialize 22
       498 ?        Ss     0:00 /usr/lib/systemd/systemd-journald
       534 ?        Ss     0:00 /usr/lib/systemd/systemd-udevd
       744 ?        Ss     0:00 /usr/lib/systemd/systemd-logind

    也可以通过-C选项来实现同样的功能。

    -C cmdlist:根据命令名称列表来匹配进程。

    [root@C7 ~]# ps -C systemd,systemd-journald,systemd-udevd,systemd-logind -f
    UID         PID   PPID  C STIME TTY          TIME CMD
    root          1      0  0 11:04 ?        00:00:02 /usr/lib/systemd/systemd --switched-root --system --deserialize 22
    root        498      1  0 11:04 ?        00:00:00 /usr/lib/systemd/systemd-journald
    root        534      1  0 11:04 ?        00:00:00 /usr/lib/systemd/systemd-udevd
    root        744      1  0 11:04 ?        00:00:00 /usr/lib/systemd/systemd-logind

    这里的列表,既不支持glob,也不支持RE。而且它是精确匹配。

    [root@C7 ~]# ps -C "systemd*"
       PID TTY          TIME CMD
    [root@C7 ~]# ps -C "systemd.*"
       PID TTY          TIME CMD
    [root@C7 ~]# ps -C "system"
       PID TTY          TIME CMD

    pgrep, pkill

    pgrep基于pattern或者其他属性查找进程,默认会输出其PID。

    pkill基于pattern或者其他属性向进程发送信号(默认是SIGTERM),不会输出进程信息。

    # pgrep [options] pattern
    # pkill [options] pattern

    大部分选项是pgrep和pkill共用的,如果有专用,会单独说明。

    pgrep

    为了做测试,我们安装了一个apache httpd的服务。

    # yum -y install httpd
    # systemctl status httpd
    ● httpd.service - The Apache HTTP Server
       Loaded: loaded (/usr/lib/systemd/system/httpd.service; disabled; vendor preset: disabled)
       Active: active (running) since Thu 2019-07-11 15:32:51 CST; 28min ago
         Docs: man:httpd(8)
               man:apachectl(8)
     Main PID: 5632 (httpd)
       Status: "Total requests: 10; Current requests/sec: 0; Current traffic:   0 B/sec"
        Tasks: 9
       CGroup: /system.slice/httpd.service
               ├─5632 /usr/sbin/httpd -DFOREGROUND
               ├─5643 /usr/sbin/httpd -DFOREGROUND
               ├─5644 /usr/sbin/httpd -DFOREGROUND
               ├─5645 /usr/sbin/httpd -DFOREGROUND
               ├─5646 /usr/sbin/httpd -DFOREGROUND
               ├─5648 /usr/sbin/httpd -DFOREGROUND
               ├─5754 /usr/sbin/httpd -DFOREGROUND
               ├─5755 /usr/sbin/httpd -DFOREGROUND
               └─5756 /usr/sbin/httpd -DFOREGROUND
    
    Jul 11 15:31:29 C7 systemd[1]: Starting The Apache HTTP Server...
    Jul 11 15:32:12 C7 httpd[5632]: AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using fe80::7ebe:48aa:260c:1099. Set the 'ServerName... this message
    Jul 11 15:32:51 C7 systemd[1]: Started The Apache HTTP Server.
    Hint: Some lines were ellipsized, use -l to show in full.

    这里的pattern,是基于程序文件名称来匹配的。

    COMMAND
    /usr/sbin/httpd -DFOREGROUND

    就是上面红色粗体字部分,其余部分不是用来和pattern进行匹配的。如果你匹配“sbin”或者“FORE”,那么是无法匹配出来的。

    匹配是模糊匹配,“httpd”可被“http”所匹配。

    默认返回pattern的PID。

    [root@C7 ~]# pgrep httpd
    5632
    5643
    5644
    5645
    5646
    5648
    5754
    5755
    5756

    可通过命令结果引用显示对应的进程信息。

    [root@C7 ~]# ps $(pgrep httpd)
       PID TTY      STAT   TIME COMMAND
      5632 ?        Ss     0:00 /usr/sbin/httpd -DFOREGROUND
      5643 ?        S      0:00 /usr/sbin/httpd -DFOREGROUND
      5644 ?        S      0:00 /usr/sbin/httpd -DFOREGROUND
      5645 ?        S      0:00 /usr/sbin/httpd -DFOREGROUND
      5646 ?        S      0:00 /usr/sbin/httpd -DFOREGROUND
      5648 ?        S      0:00 /usr/sbin/httpd -DFOREGROUND
      5754 ?        S      0:00 /usr/sbin/httpd -DFOREGROUND
      5755 ?        S      0:00 /usr/sbin/httpd -DFOREGROUND
      5756 ?        S      0:00 /usr/sbin/httpd -DFOREGROUND

    -c, --count:返回匹配pattern的进程统计计数,没匹配到就返回0。

    [root@C7 ~]# pgrep -c httpd
    9
    [root@C7 ~]# pgrep -c redis
    0

    -f, --full:上面我们说了,pattern的匹配,是仅根据程序文件名称,不包括程序的路径、命令选项、命令参数等。而启用该选项的话,就可以对整个完整的进程信息进行匹配了。

    [root@C7 ~]# pgrep -c GROUND
    0
    [root@C7 ~]# pgrep -cf GROUND
    9
    [root@C7 ~]# pgrep -c sbin
    0
    [root@C7 ~]# pgrep -cf sbin
    35

    -l, --list-name:默认情况下只显示PID,使用该选项还可显示进程名称。不过仅仅只是进程名称而已,一般使用-a选项来代替它。

    -a, --list-full:显示PID和完整的命令行信息。-l和-a都是仅适用于pgrep。

    [root@C7 ~]# pgrep -a httpd
    2129 /usr/sbin/httpd -DFOREGROUND
    2148 /usr/sbin/httpd -DFOREGROUND
    2149 /usr/sbin/httpd -DFOREGROUND
    2150 /usr/sbin/httpd -DFOREGROUND
    2152 /usr/sbin/httpd -DFOREGROUND
    2153 /usr/sbin/httpd -DFOREGROUND

    -P, --parent ppid,...:根据父进程ID来过滤。

    [root@C7 ~]# pgrep -a -P 2129
    2148 /usr/sbin/httpd -DFOREGROUND
    2149 /usr/sbin/httpd -DFOREGROUND
    2150 /usr/sbin/httpd -DFOREGROUND
    2152 /usr/sbin/httpd -DFOREGROUND
    2153 /usr/sbin/httpd -DFOREGROUND

    -u, --euid euid,...:根据用户名或者UID来过滤进程。

    [root@C7 ~]# pgrep -a -u apache
    2148 /usr/sbin/httpd -DFOREGROUND
    2149 /usr/sbin/httpd -DFOREGROUND
    2150 /usr/sbin/httpd -DFOREGROUND
    2152 /usr/sbin/httpd -DFOREGROUND
    2153 /usr/sbin/httpd -DFOREGROUND

    显示属主为root的sshd进程。

    [root@C7 ~]# pgrep -u root sshd

    显示属主为postfix或者nobody的进程。

    [root@C7 ~]# pgrep -u postfix,nobody

    -v, --inverse:反向匹配,等同于“grep -v”。不过该选项的意义并不大,尤其是在使用pkill的时候,容易误kill进程。因此pkill情况下只能使用长选项--inverse。不过还是建议不使用该选项,尤其是pkill。

    -x, --exact:精确匹配。默认是上面说的模糊匹配。例如这个进程。

    # /usr/bin/dnsmasq --conf-file=/var/lib/libvirt/dnsmasq/default.conf --leasefile-ro --dhcp-script=/usr/libexec/libvirt_leaseshelper

    默认情况下,“dns”或者“masq”都可以匹配到。使用该选项后,必须使用“dnsmasq”。

    如果搭配-f选项的话,那么必须使用“/usr/sbin/dnsmasq --conf-file=/var/lib/libvirt/dnsmasq/default.conf --leasefile-ro --dhcp-script=/usr/libexec/libvirt_leaseshelper”才可以匹配成功。

    pgrep一般用于命令结果引用,结合其他命令一起使用。

    显示所有xterm进程的信息。
    $ ps -fp $(pgrep -d, -x xterm)
    调整所有netscape进程的nice值。
    $ renice +4 $(pgrep netscape)

    pkill

    向某类进程发送信号。默认发送的是SIGTERM信号,因此这里终止了所有的httpd进程。

    [root@C7 ~]# pkill httpd

    我本人不太建议使用pkill来终止服务类的进程,因为这么做,会造成这类进程的状态异常。

    即便在再次启动服务后,也会有异常。

    应该使用systemd来管理服务类进程。

    可指定其他信号。

    # pkill -SIG ...
    # pkill --signal SIG ...

    关于信号,在kill命令中会介绍。

    pidof

    返回进程的PID。

    pidof [-s] [-c] [-n] [-x] [-m] [-o omitpid[,omitpid..]]  [-o omitpid[,omitpid..]..]  program [program..]

    program,一般是命令的名称或者完整路径,不可带命令的选项。

    [root@C7 ~]# ps -f 760
    UID         PID   PPID  C STIME TTY      STAT   TIME CMD
    root        760      1  0 09:38 ?        Ss     0:01 /sbin/rngd -f
    [root@C7 ~]# pidof rngd
    760
    [root@C7 ~]# pidof /sbin/rngd
    760
    [root@C7 ~]# pidof /sbin/rngd -f
    pidof: invalid options on command line!
    
    [root@C7 ~]# pidof "/sbin/rngd -f"
    [root@C7 ~]#

    当进程有多个PID的时候,返回多个,以空格作为分隔符。

    [root@C7 ~]# pidof httpd
    2237 2236 2235 2234 2233 2211

    我看了pidof的其他选项,有点懵逼,并且我感觉这个命令的作用不是很大,和pgrep的功能似乎是一样的。

    pidof和killall5是同一个程序。后者用于向除了线程和自身会话的进程以外的所有进程发送信号。

    [root@C7 ~]# ls -l /usr/sbin/pidof 
    lrwxrwxrwx. 1 root root 18 Sep 27  2018 /usr/sbin/pidof -> /usr/sbin/killall5

    top

    ps命令,以快照的形式显示系统当前进程信息。如果想要以动态的形式显示进程信息的话,则可以使用top命令。

    直接键入top回车后,如图显示。

    默认情况下,是每隔3秒变化一次,最上面的部分是一些汇总信息,中间空行是用于用户键入,下面的剩余部分是进程信息,进程信息默认以PID字段升序排序。

    在该界面下,可通过直接键入命令来做一些管理,例如控制变化间隔时间、排序字段、汇总信息显示等。

    常用的命令有2个。

    h:显示简要帮助信息。

    q:退出top。

    注意,在默认情况下,由于只能显示一个屏幕,因此进程信息是不全的。

    输出信息说明

    注意:如果有涉及到内存的但是没有给出单位,那么单位应该是KB。打算以不同的单位来换算的话,详见man手册中的e和E交互式命令。

    第一行

    第一行输出的信息,刚好是uptime命令所输出的信息。详见下文的uptime命令。

    第二行

    Tasks: 187 total,   1 running, 186 sleeping,   0 stopped,   0 zombie

    系统任务信息汇总,即进程的相关信息。

    一共有187个进程,1个在运行,186个处于睡眠状态,没有停止和僵尸进程。

    第三行

    %Cpu(s):  0.0 us,  1.6 sy,  0.0 ni, 98.4 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st

    us:表示用户(user)空间中的进程所占用的CPU资源百分比。这类进程是没有修改过nice值的,即un-niced。

    sy:表示内核空间中的进程所占用的CPU资源百分比。即系统(system)所使用的资源。

    ni:表示用户空间中,调整过nice值得进程所占用的CPU资源百分比。

    id:表示CPU处于空闲(idle)状态的百分比。

    wa:表示CPU处于等待IO(IO-wait)状态的百分比。

    hi:表示CPU处于硬中断时间的百分比。

    si:表示CPU处于软中断时间的百分比。

    st:表示用于虚拟机服务的时间百分比。

    第四行

    KiB Mem :   997980 total,   133396 free,   464344 used,   400240 buff/cache

    这行表示的是物理内存。

    total:总内存。

    free:完全空闲的内存。

    used:真实已使用的内存。

    buff/cache:被使用的内存中(不是used),用于buffer或者cache的部分,这部分是还可以再利用的。因此我们看一个系统的物理内存剩余情况,一般要看free+buff/cache的和值。

    total=free+used+buff/cache

    第五行

    KiB Swap:  2097148 total,  2097148 free,        0 used.   318028 avail Mem

    swap表示的是交换分区。交换分区一般是物理磁盘上的区域,用于当内存资源不足的时候,系统依据某些算法(如LRU)将内存中数据交换到磁盘中的交换分区上存放。

    因此交换分区肯定是系统可以不使用,那是最好的。毕竟物理磁盘的速度远远慢于内存。

    在man手册中,也将这部分称之为了虚拟内存。(存疑)应该是相对于物理内存,所以才这么说的。

    前面三个字段很好理解,分别表示了交换分区的总量(total)、剩余(free)和已使用(used)。

    在我们的实验机上,由于没有负载,物理内存完全够用,因此这里是完全没有用到swap分区,这很棒!

    avail Mem:表示在不使用交换分区的情况下,如果启用一个新的程序,那么系统上有多少物理内存资源可用。这是一个近似值。不像free字段,it attempts to account for readily reclaimable page cache and memory slabs. 它和内核的版本也有关系,在3.14上是可用的,在2.6.27+上是仿真的,其他情况下等同于free。

    第六行

    Change delay from 3.0 to

    这行一般情况下是空的,用于命令的提示和键入命令等。例如我们交互式命令d用于修改刷新间隔,然后会在该行出现提示,要求我们输入新的刷新间隔时间。

    第七行

       PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND                                                                                                              
       757 root      20   0   21668   1296    988 S   0.7  0.1   0:00.13 irqbalance                                                                                                           
      2111 root      20   0  161988   2360   1592 R   0.7  0.2   0:00.05 top                                                                                                                  
        37 root      20   0       0      0      0 S   0.3  0.0   0:00.46 kworker/1:1                                                                                                          
       113 root      20   0       0      0      0 S   0.3  0.0   0:00.42 kworker/0:2

    常见的就不再说明了。

    PR:任务的调度优先级(scheduling priority)。越小越优先。如果值为rt的话,表示任务运行于实时调度优先级下。实时优先级的意思可能是任务总是可以抢占(preempt)CPU的资源。

    NI:任务的nice值,越小越优先级。这个值的变化,也会影响到PR。NI值为-20的时候,PR值会为0。

    VIRT:虚拟内存的总值。包含了所有的代码、数据和共享库,加上被交换出去的页面和被映射但是还未使用的页面。

    RES:常驻(resident)内存的大小。常驻内存应该才是我们所通常说的内存,而上面的VIRT包含了许多其他的“内存”例如swap等。

    SHR:共享(shared)内存的大小。并不是所有的共享内存都是常驻的,它只是反映了潜在地可被共享给其他进程的内存大小。

    S:进程状态。D(不可中断睡眠)、R(运行)、S(睡眠)、T(被作业控制信号所停止)、t(在追踪的过程中被调试器所停止)和Z(僵尸进程)。

    %CPU:可简单的理解为CPU占用百分比,不过它是可以超过100%的,具体可见man手册的字段说明。

    %MEM:指物理内存占用的百分比。即常驻内存。

    TIME+:和TIME字段的含义是相同的,表示进程占用CPU的总时间,不过该字段的反馈更加细粒度,可精确到百分之一秒。

    COMMAND:就是命令了,默认情况下只显示命令的名称,可通过交互式命令c来切换命令名称与命令行的显示。命令行的意思就是带参数的完全的命令。显示命令行的情况下,内核显示会以中括号的形式显示,例如“[ksoftirqd/0]”。

    选项说明

    -v和-h:用于显示库版本以及选项使用提示。

    # top -v
    或者
    # top -h
      procps-ng version 3.3.10
    Usage:
      top -hv | -bcHiOSs -d secs -n max -u|U user -p pid(s) -o field -w [cols]

    top的选项,可以不加连接号(-)或者不需要空格。知道即可,一般不会这么使用。

    # top h
    # top v

    -d #:以指定的时间间隔刷新,单位是秒,默认是3秒。

    -b:启用批处理(batch)模式。默认情况下的top输出,是输出到屏幕,并且在每个间隔时间后刷新一次,刷新的数据会覆盖之前的数据。而启用批处理模式后,每次输出都不会进行覆盖操作,这有利于我们将top的结果输出到其他程序或文件中。如果结合-n选项的话,可指定批处理模式在运行几次后自动退出,否则就需要用户自己键入Ctrl+c来退出。批处理模式下显示的进程信息是全的。

    # top -b -n 3

    本打算像pgrep/pkill那样看man手册来尽可能详述一下,但是看到top的man手册如此大的篇幅量,暂且放弃了,列出一些马哥说的常用的即可。

    另外,个人感觉,当内功心法(计算机基础、英语等)不够的时候,不可以直接就上来学习一些上乘的武功(比如直接照着一个几千行的man手册等)。

    排序

    M:以%MEM内存字段排序。

    N:以PID字段排序。

    P:以CPU使用率%CPU字段排序。

    T:以使用CPU时间TIME+字段排序。

    R:上面说的四个排序字段,默认都是降序排序,想要改变升降序的话,使用R。

    汇总信息显示开关

    l:第一行信息的显示开关。

    top - 14:32:16 up  5:18,  2 users,  load average: 0.00, 0.01, 0.05

    t:控制任务(即进程)和CPU相关信息的显示开关。一共有四种显示模式,下面是第一种。

    Tasks: 190 total,   1 running, 189 sleeping,   0 stopped,   0 zombie
    %Cpu(s):  0.0 us,  0.0 sy,  0.0 ni,100.0 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st

    第二种和第三种模式都是将CPU资源按照一个使用进度条来显示,一种是条状图形,另一种是块状图形,我个人实验环境,没有什么负载,因此无法看出区别。

    Tasks: 189 total,   2 running, 187 sleeping,   0 stopped,   0 zombie
    %Cpu(s):   0.0/0.0     0[                                                                                                    ]
    Tasks: 189 total,   2 running, 187 sleeping,   0 stopped,   0 zombie
    %Cpu(s):   0.0/0.5     0[                                                                                                    ]

    第四种就是直接关闭显示了。在CentOS 6上,则只有开关显示而已。

    m:内存的显示控制,和t命令一样,也有四种模式。因为内存的数据比较丰富,就可以看出条状图形和块状图形的区别了。

    其他命令

    s|d:可用于修改top显示的间隔时间,单位是秒,键入数字后回车即可。

    k:选择某个PID并选择向其发送的信号。PID为0表示top命令自身,默认的信号是15/SIGTERM。

    r:调整某个进程的nice值。

    uptime

    显示的信息,和top的首行信息一致。

    [root@C7 ~]# uptime
     15:46:29 up  6:32,  2 users,  load average: 0.00, 0.01, 0.05

    15:46:29:表示当前的时间。

    up    6:32:表示系统已启动的时间。可通过-p选项来使得显示更加直观。

    [root@C7 ~]# uptime -p
    up 6 hours, 32 minutes

    想知道系统的启动时间的话,我们可以自己推算,也可以使用-s选项。

    [root@C7 ~]# uptime -s
    2019-07-19 09:13:51

    2 users:表示当前系统在线用户数。

    load average: 0.00, 0.01, 0.05:这个表示系统的平均负载。一共有3个数字。

    • 第一个数字:系统在过去1分钟内的平均负载。
    • 第二个数字:系统在过去5分钟内的平均负载。
    • 第三个数字:系统在过去15分钟内的平均负载。

    平均负载表示的是处于可运行态(runnable)或者不可中断态(uninterruptable)的进程的数量的平均值。可运行态表示的是进程正在使用或者等待使用CPU资源。不可中断态表示的是进程正处于等待IO的情况,例如磁盘IO。

    需要注意的是,平均负载并没有针对系统的CPU核心数做专门的设计(man手册叫常规化(normalized))。举个例子,假设平均负载为1,那么在单核的CPU上就表示系统总是忙碌的,在4核的CPU上就表示系统有75%的时间处于空闲状态。

    因此判断系统是否繁忙,要将平均负载和CPU核心数结合考量。

    htop

    不知是否是由于htop是基于ncurses,它支持类似GUI的鼠标点击,如果鼠标点击在字段名上,还支持排序,反复点击字段名支持升序和降序。

    htop类似于htop,不过它的输出带有显示着色,并且更易看懂。其他的区别,没实践过,这里基于man手册,在这里也说明下。

    htop允许水平和垂直方向的滚动,因此可以看到系统上的所有的进程信息,包含完整的命令行信息。可以以进程树的形式展示进程,可以一次性选择多个进程并在其上执行一些操作。不需要输入PID即可kill或者renice进程。

    系统上很可能没htop命令,单独安装下。

    # yum install htop

    界面展示。

    -d --delay=DELAY:指定刷新的间隔,默认是1秒刷新一次。这里的单位要注意,它是十分之一秒,也就是说”-d 1“表示每隔0.1秒刷新一次。

    # htop -d 50
    每隔5秒刷新一次。

    -u --user=USERNAME:仅显示指定用户的进程。

    # htop -u postfix

    -s --sort-key COLUMN:以某个指定的字段排序。可以先查看有哪些字段是支持排序的。

    [root@C7 ~]# htop -s help
    PID
    Command
    STATE
    PPID
    ...

    排序默认是升序。

    # htop -s PID

    一些交互式命令。

    l:查看选定的进程所打开的文件列表。

    s:追踪选定进程的系统调用。

    t:以树状图形式显示进程状态。

    a:设置进程与CPU核心的绑定。

    vmstat

    用于报告虚拟内存统计信息。语法如下。

    vmstat [options] [delay [count]]

    不带任何选项和参数的情况下,只显示一次信息。

    [root@C7 ~]# vmstat 
    procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
     r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
     1  0      0 137488   2116 400088    0    0    12     1   20   18  0  0 100  0  0

    delay:每隔几秒显示一次。不支持小数。

    count:一共显示几次,如果存在delay但是省略count的话,那么将会一直循环输出。

    接下来我们来解释一下每个字段的含义。

    Procs

    • r:可运行的进程数,包含了运行中或者等待运行的。
    • b:处于不可中断睡眠状态的进程数。

    Memory

    • swpd:虚拟内存的使用数量(这里的虚拟内存,应该就是只swap中的存储吧?)。
    • free:处于空闲状态的内存数。
    • buff:作为缓冲(buffer)的内存数。
    • cache:作为缓存(cache)的内存数。

    Swap

    • si:从磁盘交换入的内存速率,单位是每秒。
    • so:交换至磁盘的内存速率。

    IO

    • bi:从块设备上接收到的块数(blocks/s)。
    • bo:发送至块设备上的块数(blocks/s)。

    System

    • in:每秒中断数,包含时钟(clock)。
    • cs:每秒发生的上下文切换数。

    CPU

    这里记录的是占CPU时间的百分比。

    • us:运行非内核级代码的时间。(用户时间,包含nice时间)
    • sy:运行内核级代码的时间。(系统时间)
    • id:处于空闲状态的时间。
    • wa:等待IO的时间。
    • st:被虚拟机所偷走(stolen)的时间。

    pmap

    根据PID查看进程的内存映射情况。

    pmap [options] pid [...]

    -x:查看扩展格式,即更详细的信息。

    # pmap 1
    # pmap -x 1

    也可以直接查看/proc目录下的文件。

    # cat /proc/PID/maps
    # cat /proc/1/maps

    glances

    是一款类似top和htop的综合监控工具。跨平台,使用python语言编写。

    最早出现的是top,htop试图取代top,而glances则试图取代前两者。

    官网是:https://nicolargo.github.io/glances/

    从站点的介绍来看,glances是一款更接近现代的监控系统,社区和文档都不错,将来可着重学习。

    它除了可以像top/htop那样独立运行以外,还支持C/S模式和web模式,并且数据可以到处成csv格式等多种格式,也可以输出到其他的监控平台如Prometheus等。

    dstat

    dstat是一个多功能的工具,它用于取代vmstat、iostat、ifstat和netstat工具。看man手册的话,有说明该工具比上述其他工具更好,例如克服了上述工具已知的一些缺点以及添加了一些额外的功能。

    也是需要单独安装的一个命令。

    # yum install dstat

    语法。

    dstat [-afv] [options..] [delay [count]]

    不带选项和参数的dstat的输出结果,默认是delay为1秒,count省略无限制,直到用户Ctrl+c退出。

    输出结果有一个很明显的特点,也是htop相对于top的特点,那就是着色。并且它还自带了单位转换。

    由于我们没有指定任何的选项,因此命令默认帮我们指定了-cdngy这5个选项。

    You did not select any stats, using -cdngy by default.

    -c, --cpu:启用CPU统计。

    -d, --disk:启用磁盘统计。

    -n, --net:启用网络统计。

    -g, --page:启用页面统计。

    -y, --sys:启用系统统计。

    在语法中,还特意将[-afv]列出来了,我们来单独看这3个选项的作用。

    -a, --all:等同于-cdngy,也就是默认的选项。

    -f, --full:扩展-C、-D、-I、-N和-S发现列表。我们先来单独看这几个大写的选项的含义。

    • -C 0,3,total:当使用-c选项时,包含cpu0、cpu3和total。
    • -D total,hda:当使用-d选项时,包含total和hda。
    • -I 5,10:当使用-i选项时,包含中断5和10。
      • -i, --int:启用中断统计。
    • -N eth1,total:当使用-n选项时,包含eth1和total。
    • -S swap1,total:当使用-s选项时,包含swap1和total。
      • -s, --swap:启用swap统计。

    默认情况下,我们对于CPU、磁盘和网卡等资源的监控,都是只显示total信息的。

    假如我们在监控CPU信息时(-c),又使用-C选项,就可以实现对具体的某个或者某些CPU核心进行监控。

    当然了,这些大写的选项后面是需要加具体的参数的,否则报错。

    [root@C7 ~]# dstat -c -C
    dstat: option -C requires argument, try dstat -h for a list of all the options

    而-f选项,则是直接将上述提到的那些指定某些实例(如CPU核心、网卡、硬盘等)的选项都带上,并且选项参数都默认扩展为系统上已发现的CPU核心、网卡和硬盘等。

    简而言之,-af可以将原本统计total的信息转变为针对具体实例的统计。

    -v, --vmstat:等同于“-pmgdsc -D total”。该选项的统计信息,应该是模仿vmstat的输出。

    -p, --proc:启用进程统计。

    -m, --mem:启用内存统计。

    --tcp:启用TCP连接相关的统计(listen, established, syn, time_wait, close)。

    --udp:启用TCP连接相关的统计(listen, active)。

    --raw:启用裸套接字相关的统计(raw sockets)。

    --socket:启用套接字相关的统计(total, tcp, udp, raw, ip-fragments)。

    --ipc:启用IPC(进程间通信)相关的统计(message queue, semaphores, shared memory)。

     --output file:以CSV格式写入到外部文件中。

    [root@C7 ~]# cat dstat_along.csv 
    "Dstat 0.7.2 CSV output"
    "Author:","Dag Wieers <dag@wieers.com>",,,,"URL:","http://dag.wieers.com/home-made/dstat/"
    "Host:","C7",,,,"User:","root"
    "Cmdline:","dstat --output dstat_along.csv 1 2",,,,"Date:","05 Aug 2019 14:43:30 CST"
    
    "total cpu usage",,,,,,"dsk/total",,"net/total",,"paging",,"system",
    "usr","sys","idl","wai","hiq","siq","read","writ","recv","send","in","out","int","csw"
    0.020,0.066,99.907,0.006,0.0,0.001,19724.801,2191.394,0.0,0.0,0.0,0.0,72.748,64.299
    0.0,0.0,100.0,0.0,0.0,0.0,0.0,0.0,106.0,902.0,0.0,0.0,72.0,55.0
    0.249,0.249,99.501,0.0,0.0,0.0,0.0,0.0,60.0,362.0,0.0,0.0,92.0,71.0

    --noupdate:当delay大于1的时候,例如3,并不是每隔3秒才会显示一次,在3秒内的每隔一秒,都会显示一次中间状态值,就是下图中红色没加粗的字体。使用该选项的话,会禁用这种机制。

    这个中间状态值是在这段时间内的平均值,而不是快照值。例如delay等于10,那么前9次的值,分别是前1秒的平均值、前2秒的平均值。。。前9秒的平均值。最后的值,是前10秒的平均值。

    dstat中可包含插件用于扩展其功能,插件有内部和外部之分,用户可自行开发插件或者参与到插件的开发(contribute,贡献)。

    内部插件应该是dstat自带的。外部插件才是用户开发的。

    --list:列出内部和外部插件。

    [root@C7 ~]# dstat --list
    internal:
        aio, cpu, cpu24, disk, disk24, disk24old, epoch, fs, int, int24, io, ipc, load, lock, mem, net, page, page24, proc, raw, socket, swap, swapold, sys, tcp, time, udp, unix, vm
    /usr/share/dstat:
        battery, battery-remain, cpufreq, dbus, disk-tps, disk-util, dstat, dstat-cpu, dstat-ctxt, dstat-mem, fan, freespace, gpfs, gpfs-ops, helloworld, innodb-buffer, innodb-io, 
        innodb-ops, lustre, memcache-hits, mysql-io, mysql-keys, mysql5-cmds, mysql5-conn, mysql5-io, mysql5-keys, net-packets, nfs3, nfs3-ops, nfsd3, nfsd3-ops, ntp, postfix, power, 
        proc-count, qmail, rpc, rpcd, sendmail, snooze, squid, test, thermal, top-bio, top-bio-adv, top-childwait, top-cpu, top-cpu-adv, top-cputime, top-cputime-avg, top-int, top-io, 
        top-io-adv, top-latency, top-latency-avg, top-mem, top-oom, utmp, vm-memctl, vmk-hba, vmk-int, vmk-nic, vz-cpu, vz-io, vz-ubc, wifi

    --plugin-name:基于插件的名称来启用外部插件。这里的“--plugin-name”是需要替换成具体的插件名称的。这些在man手册的PLUGINS中可查看具体的每个插件名称。

    例如--dbus和--dstat。

    而有一些插件,则是需要其他条件的支持才可使用的。

    [root@C7 ~]# dstat --battery 1 2
    Module dstat_battery failed to load. (No ACPI battery information found.)
    None of the stats you selected are available.

    dstat支持一些top系列的插件,用于显示最占用某些资源的进程。

    --top-cpu:显示最占用CPU的进程。

    --top-mem:显示最占用内存的进程。

    --top-oom:显示当内存不足时,显示最容易被OOM机制所kill掉的进程,这个在内存不足时还是蛮有用的。

    --top-io:显示最占用IO的进程。

    --top-latency:显示延迟最高的进程,单位毫秒。

    -t, --time:在输出的时候,加上当前的日期和时间信息,某些情况下可能有用。该选项一般放最前。

    kill和killall

    进程间通信,包含了信号(signal)机制。而kill命令,则用于向进程发送信号。

    不过需要注意的是,kill命令,有2个,一个是bash内置命令,另一个是外部命令。

    当我们直接键入kill命令的时候,就是使用内置命令。

    可通过type命令来判断。

    [root@C7 ~]# type kill
    kill is a shell builtin

    想使用外部的kill命令的话,可通过which来判断其绝对路径,然后键入绝对路径来执行。

    [root@C7 ~]# which kill
    /usr/bin/kill

    查看内置命令用法使用help命令,查看外部命令用法使用man命令。

    # help kill
    # man kill

    查看完帮助后,发现外部kill命令有--help选项,而内置的kill命令是没有的,因此可使用该选项来判断你所使用的到底是内置还是外部。

    [root@C7 ~]# kill --help
    -bash: kill: -help: invalid signal specification
    [root@C7 ~]# /usr/bin/kill --help
    ... ...

    本文所阐述的是内置的kill命令。

    kill命令会成为shell内置命令有两点原因。

    1. 它允许了作业(job)ID可以被使用,而不仅仅是PID。
    2. 它允许用户在系统进程数已达到最大值的时候依然可以kill进程。注:若使用的是外部命令,则必须再发起一个新进程,而此时由于达到了进程上限,因此无法再发起新进程也就无法再使用外部命令了。而内置命令存在于当前shell进程中,无需再创建新进程。

    -l:列出所有的信号。

    [root@C7 ~]# kill -l
     1) SIGHUP     2) SIGINT     3) SIGQUIT     4) SIGILL     5) SIGTRAP
     6) SIGABRT     7) SIGBUS     8) SIGFPE     9) SIGKILL    10) SIGUSR1
    11) SIGSEGV    12) SIGUSR2    13) SIGPIPE    14) SIGALRM    15) SIGTERM
    16) SIGSTKFLT    17) SIGCHLD    18) SIGCONT    19) SIGSTOP    20) SIGTSTP
    21) SIGTTIN    22) SIGTTOU    23) SIGURG    24) SIGXCPU    25) SIGXFSZ
    26) SIGVTALRM    27) SIGPROF    28) SIGWINCH    29) SIGIO    30) SIGPWR
    31) SIGSYS    34) SIGRTMIN    35) SIGRTMIN+1    36) SIGRTMIN+2    37) SIGRTMIN+3
    38) SIGRTMIN+4    39) SIGRTMIN+5    40) SIGRTMIN+6    41) SIGRTMIN+7    42) SIGRTMIN+8
    43) SIGRTMIN+9    44) SIGRTMIN+10    45) SIGRTMIN+11    46) SIGRTMIN+12    47) SIGRTMIN+13
    48) SIGRTMIN+14    49) SIGRTMIN+15    50) SIGRTMAX-14    51) SIGRTMAX-13    52) SIGRTMAX-12
    53) SIGRTMAX-11    54) SIGRTMAX-10    55) SIGRTMAX-9    56) SIGRTMAX-8    57) SIGRTMAX-7
    58) SIGRTMAX-6    59) SIGRTMAX-5    60) SIGRTMAX-4    61) SIGRTMAX-3    62) SIGRTMAX-2
    63) SIGRTMAX-1    64) SIGRTMAX

    信号的表示方法有三种。

    • 数字,例如1。
    • 完整名称,例如SIGHUP。
    • 简写名称,例如HUP。
    # kill -s 15 PID
    # kill -s SIGTERM PID
    # kill -s TERM PID

    常用的信号:

    • 1(SIGHUP):在不停止进程的情况下使其重载配置文件;一般的服务的reload函数就是调用此命令;
    • 2(SIGINT):interrupt,打断正在运行的进程,等同于在终端键入Ctrl + c;
    • 9(SIGKILL):直接杀死正在运行的进程;
    • 15(SIGTERM):终止运行中的进程;一般的服务的stop函数就是调用此命令(个人见解);这是默认的信号;
    • 18(SIGCONT):继续被停止的进程;
    • 19(SIGSTOP):停止进程,等同于在进程运行时键入Ctrl + z或者命令执行的时候加入后台符号&;

    kill基于PID来向进程发送信号,而killall则可以根据进程名来发送信号。和kill类似,其默认的信号是SIGTERM,-s选项用于指定信号。

    其作用应该是和pkill一样的,不过默认情况下pkill的进程名是模糊匹配,而killall则必须完全匹配进程名。

    [root@C7 ~]# ps axu | grep -E "redis|httpd"
    redis      2996  0.1  0.5 142956  5796 ?        Ssl  15:11   0:00 /usr/bin/redis-server 127.0.0.1:6379
    root       3028  0.0  0.5 230376  5164 ?        Ss   15:12   0:00 /usr/sbin/httpd -DFOREGROUND
    apache     3045  0.0  0.3 232460  3148 ?        S    15:13   0:00 /usr/sbin/httpd -DFOREGROUND
    apache     3046  0.0  0.3 232460  3148 ?        S    15:13   0:00 /usr/sbin/httpd -DFOREGROUND
    apache     3047  0.0  0.3 232460  3148 ?        S    15:13   0:00 /usr/sbin/httpd -DFOREGROUND
    apache     3048  0.0  0.3 232460  3148 ?        S    15:13   0:00 /usr/sbin/httpd -DFOREGROUND
    apache     3050  0.0  0.3 232460  3148 ?        S    15:13   0:00 /usr/sbin/httpd -DFOREGROUND
    root       3113  0.0  0.0 112708   988 pts/1    S+   15:17   0:00 grep --color=auto -E redis|httpd
    [root@C7 ~]# killall http
    http: no process found
    [root@C7 ~]# killall httpd
    [root@C7 ~]# killall redis
    redis: no process found
    [root@C7 ~]# killall redis-server
    [root@C7 ~]# ps axu | grep -E "redis|httpd"
    root       3149  0.0  0.0 112708   988 pts/1    S+   15:18   0:00 grep --color=auto -E redis|httpd

    想要改变killall的匹配进程名的规则,例如启用RE;或者想根据安全上下文(涉及selinux)、用户名来向进程发送信号。这些,killall都是支持的,详见man手册中的选项说明。

    结语

    还有许许多多和进程相关的其他命令。

    • 进程作业(job)系统:jobs、bg、fg。
    • 进程优先级:nice、renice。

    该篇篇幅太长了,就不展开了。另外,也感慨虽然这篇随笔的篇幅很长,但是大多是比较凌乱的知识点,并且个人对其准确性也不敢完全保证。

    并且深度也不够,惭愧惭愧,权当笔记了。

  • 相关阅读:
    Git代码行数统计命令
    JPA访问数据库的几种方式
    爱码小士丨代码一敲十年,收入虽高前途摇摆
    “肉瘾”女孩从软件测试工程师到主管的成长感悟
    华为测试大牛Python+Django接口自动化怎么写的?
    携程大牛的单元测试是怎么样写的?
    Jmeter参数的AES加密使用
    弄啥嘞?热爱你的Bug
    “进腾讯工作一个月,我想辞职了”
    我在华为,软件测试人员在工作中如何运用Linux?
  • 原文地址:https://www.cnblogs.com/alongdidi/p/linux_process.html
Copyright © 2020-2023  润新知