Skip to content

18 进程

1. 查看进程

1.1 ps

静态查看。

ps aux  查看系统中所有的进程
ps -l   较长、较详细地输出信息
ps axjf 以进程树方式列出

-a      不与 terminal 有关的所有 process ;
-u      有效使用者 (effective user) 相关的 process ;
-e, -A  选择全部的进程
-f      完整格式地输出

Output formats:
x       通常与 a 这个参数一起使用,可列出较完整信息。注意,不是 -a 参数。aux 与 -aux 是不一样的!
f, --forest         ascii art process tree
j                   BSD job control format
[root@dev ~]# ps -l
F S   UID    PID   PPID  C PRI  NI ADDR SZ WCHAN  TTY          TIME CMD
4 S     0  15352   3303  0  80   0 - 29238 do_wai pts/7    00:00:00 bash
0 R     0  17428  15352  0  80   0 - 38312 -      pts/7    00:00:00 ps

各个字段的含义:

  1. F:进程的标志位。
  2. 1 forked but didn't exec
  3. 4 used super-user privileges
  4. S:进程的状态位。
  5. D uninterruptible sleep (usually IO)
  6. R running or runnable (on run queue)
  7. S interruptible sleep (waiting for an event to complete)
  8. T stopped by job control signal
  9. t stopped by debugger during the tracing
  10. W paging (not valid since the 2.6.xx kernel)
  11. X dead (should never be seen)
  12. Z defunct ("zombie") process, terminated but not reaped by its parent
  13. C:CPU使用率
  14. PRI:进程的优先级。数字越低优先级越高。
  15. NI:nice 值。范围: 19 (nicest) to -20 (not nice to others)。具体说明参考下文。
  16. ADDR:kernel function,指出该进程在内存的哪个部分,如果是个 running 的进程,一般就会显示-
  17. SZ:在进程核心映像的物理页面中的大小。用掉多少内存。
  18. WCHAN:进程是处于休眠状态的kernel function名称。-代表running;*代表多线程。
  19. TIME:此进程实际花费 CPU 运作的时间
[root@dev ~]# ps aux
USER        PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root          1  0.0  0.0 194044  7216 ?        Ss   Nov04   0:09 /usr/lib/systemd/systemd --switched-root --system --deserialize 22
root          2  0.0  0.0      0     0 ?        S    Nov04   0:00 [kthreadd]
root          4  0.0  0.0      0     0 ?        S<   Nov04   0:00 [kworker/0:0H]
root          6  0.0  0.0      0     0 ?        S    Nov04   0:01 [ksoftirqd/0]
……
root      18454  0.0  0.0 155372  1872 pts/7    R+   15:15   0:00 ps aux

各个字段的含义:

  1. VSZ:该 process 使用掉的虚拟内存量 (Kbytes)
  2. RSS:该 process 占用的固定的内存量 (Kbytes)
  3. TTY:与终端无关时为?
  4. STAT:同S
  5. START:启动时间,若时间过长,则不会列出具体时间点
[root@dev ~]# ps axjf
  PPID    PID   PGID    SID TTY       TPGID STAT   UID   TIME COMMAND
  3303  17492  17492  17492 pts/8     17534 Ss       0   0:00  \_ -bash
 17492  17533  17533  17492 pts/8     17534 S        0   0:00      \_ su sink
 17533  17534  17534  17492 pts/8     17534 S+    1000   0:00          \_ bash
[root@dev ~]# ps axf
   PID TTY      STAT   TIME COMMAND

1.2 top

动态查看。

top -bcHiOSs -d secs -n max -u|U user -p pid -o fld -w [cols]

Options
    -d      几秒更新一次
    -b      批量模式。在将信息输出到其他程序或文件时很有用
    -n      与 -b 搭配使用,表示迭代多少次
    -o      按照哪个字段排序。在字段前添加特殊符号指定顺序还是降序:+表示降序排列;-表示升序排列。
# 3秒更新一次,以 PID 降序排序
[root@dev ~]# top -d 3 -o -PID
top - 09:52:18 up 2 days,  1:11, 10 users,  load average: 0.37, 0.40, 0.34
Tasks: 292 total,   1 running, 291 sleeping,   0 stopped,   0 zombie
%Cpu(s):  4.1 us,  4.1 sy,  0.0 ni, 91.9 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem : 16247672 total,  6168780 free,  5853688 used,  4225204 buff/cache
KiB Swap:  5242876 total,  5242876 free,        0 used.  9880640 avail Mem 

   PID USER      PR  NI    VIRT    RES    SHR S  %CPU %MEM     TIME+ COMMAND
     1 root      20   0  194044   7216   4180 S   0.0  0.0   0:12.42 systemd
     2 root      20   0       0      0      0 S   0.0  0.0   0:00.24 kthreadd
     4 root       0 -20       0      0      0 S   0.0  0.0   0:00.00 kworker/0:0H

上半部分的内容:

  • 第一行:
  • 当前时间是 09:52:18。
  • 已经开机2天1小时11分钟了。
  • 已登入系统的人数。同一个账户可在不同终端同时登入。
  • 系统在 1, 5, 15 分钟的平均工作负载。工作负载是系统平均要负责运作几个进程(工作)的意思。
  • 第二行,表示进程的总体状态
  • 第三行,表示 CPU 的整体负载
  • us, user : time running un-niced user processes
  • sy, system : time running kernel processes
  • ni, nice : time running niced user processes
  • id, idle : time spent in the kernel idle handler,内核空闲
  • wa, IO-wait : time waiting for I/O completion。如果是多核心的设备,可以按下数字键1来切换成不同CPU 的负载率。
  • hi : time spent servicing hardware interrupts
  • si : time spent servicing software interrupts
  • st : time stolen from this vm by the hypervisor
  • 第四行,表示物理内存的使用情况
  • 第五行,表示虚拟内存的使用情况

下半部分的内容:

  • PR:优先级
  • NI:nice,与PR有关,也是越小越早被执行
# 将三次的结果输出到文件
[root@dev ~]# top -b -n 3 > top.log
# 只查看指定的进程
[root@dev ~]# top -p 1 -p 4

其实在执行top之后还有一些指令可以执行,按下h来查看吧。

1.3 pstree

显示进程树。

pstree [options] [pid, user]

options
    -A     Use ASCII characters to draw the tree.
    -U     Use UTF-8 (Unicode) line drawing characters.
    -p     Show PIDs.
    -u     Show uid transitions.
[root@dev ~]# pstree -pu  | grep sink
           |                       |-bash(17492)---su(17533)---bash(17534,sink)
[root@dev ~]# pstree -pu 2883
xdg-permission-(2883)─┬─{xdg-permission-}(2884)
                      └─{xdg-permission-}(2886)
[root@dev ~]# pstree -pu sink
bash(17534)

2. 结束进程

killall可以通过进程的名字来杀掉进程。

killall [options] [--] command_name ...

options
    -e, --exact             精确匹配 command_name。不得超过15个字符
    -i, --interactive       在 kill 进程之前交互式地询问
    -I, --ignore-case       忽略大小写
    -l, --list              List all known signal names.
    -s, --signal            Send this signal instead of SIGTERM.
    -u, --user              Kill only processes the specified user owns.Command names are optional.
[root@dev ~]# killall -9 httpd

3. 进程执行顺序

进程的优先执行序 (Priority) 与 CPU 排程。CPU 排程指的是每支进程被 CPU 运作的演算规则。

3.1 Priority 与 Nice 值

PRI (Priority) 值是由内核动态调整的, 用户无法直接调整 PRI 值的。

如果你想要调整进程的优先执行序时,就得要透过 NI (Nice) 值了。

PRI 与 NI 的关系如下:

PRI(new) = PRI(old) + nice

虽然 nice 值是可以影响 PRI ,不过,最终的 PRI 仍是要经过系统分析后才会决定的。

NI 的使用事项:

  • nice 值可调整的范围为 -20 ~ 19 ;

  • root 可随意调整自己或他人进程的 Nice 值,且范围为 -20 ~ 19 ;

  • 一般使用者仅可调整自己进程的 Nice 值,且范围仅为 0 ~ 19 (避免一般用户抢占系统资源);
  • 一般使用者仅可将 nice 值越调越高,例如本来 nice 为 5 ,则未来仅能调整到大于 5;

在top运行的时候是可以通过键入r来调整nice值的。下面介绍调整 NI 的另外两种方式。

3.1.1 nice:新执行的指令即给予新的 nice 值

nice [OPTION] [COMMAND [ARG]...]

OPTION
    -n, --adjustment=N      add integer N to the niceness (default 10)
[root@dev ~]# nice -n -23 vi &
[root@dev ~]# vi &
[root@dev ~]# ps -l
F S   UID    PID   PPID  C PRI  NI ADDR SZ WCHAN  TTY          TIME CMD
4 S     0  15352   3303  0  80   0 - 29238 do_wai pts/7    00:00:00 bash
# 每次不一定会正好符合公式,内核会动态调整的
4 T     0  31430  15352  0  60 -20 - 31061 do_sig pts/7    00:00:00 vi
0 T     0  31444  15352  0  80   0 - 31061 do_sig pts/7    00:00:00 vi
0 R     0  31448  15352  0  80   0 - 38312 -      pts/7    00:00:00 ps
[root@dev ~]# killall -9 vi
[1]-  Killed                  nice -n -23 vi
[2]+  Killed                  vi

3.1.2 renice:对存在进程的 nice 重新调整

renice [-n] priority [-gpu] identifier...

OPTIONS
    -n, --priority priority     如果使用该选项,必须是第一个参数
    -g, --pgrp pgid...
    -u, --user name_or_uid...
    -p, --pid pid...
# root用户调整
[root@dev ~]# ps -l
F S   UID    PID   PPID  C PRI  NI ADDR SZ WCHAN  TTY          TIME CMD
4 S     0  15352   3303  0  80   0 - 29238 do_wai pts/7    00:00:00 bash
0 R     0  31608  15352  0  80   0 - 38312 -      pts/7    00:00:00 ps
[root@dev ~]# renice -n -5 15352
15352 (process ID) old priority 0, new priority -5
[root@dev ~]# ps -l
F S   UID    PID   PPID  C PRI  NI ADDR SZ WCHAN  TTY          TIME CMD
4 S     0  15352   3303  0  75  -5 - 29238 do_wai pts/7    00:00:00 bash
0 R     0  31615  15352  0  75  -5 - 38312 -      pts/7    00:00:00 ps
[root@dev ~]# renice -n 5 15352
15352 (process ID) old priority -5, new priority 5
[root@dev ~]# ps -l
F S   UID    PID   PPID  C PRI  NI ADDR SZ WCHAN  TTY          TIME CMD
4 S     0  15352   3303  0  85   5 - 29238 do_wai pts/7    00:00:00 bash
0 R     0  31619  15352  0  85   5 - 38312 -      pts/7    00:00:00 ps
# 普通用户调整
[sink@dev ~]$ ps -l
F S   UID    PID   PPID  C PRI  NI ADDR SZ WCHAN  TTY          TIME CMD
4 S  1000  17534  17533  0  80   0 - 29223 do_wai pts/8    00:00:00 bash
0 R  1000  31626  17534  0  80   0 - 38312 -      pts/8    00:00:00 ps
[sink@dev ~]$ renice -n -10 17534
renice: failed to set priority for 17534 (process ID): Permission denied
[sink@dev ~]$ renice 3 17534
17534 (process ID) old priority 0, new priority 3
[sink@dev ~]$ ps -l
F S   UID    PID   PPID  C PRI  NI ADDR SZ WCHAN  TTY          TIME CMD
4 S  1000  17534  17533  0  83   3 - 29223 do_wai pts/8    00:00:00 bash
0 R  1000  31649  17534  0  83   3 - 38312 -      pts/8    00:00:00 ps

在调整了 bash 的 nice 之后, ps 的nice 也跟着发生了变化,这是因为整个 nice 值是可以在父进程 --> 子进程之间传递的

4. 特殊文件与进程

4.1 具有 SUID/SGID 权限的指令执行状态

在触发具有SUID的程序后,会取得一个新的进程与 PID,该 PID 产生时透过 SUID 来给予该 PID 特殊的权限设定

[sink@dev ~]$ ll /usr/bin/passwd 
-rwsr-xr-x. 1 root root 27856 Aug  9 09:39 /usr/bin/passwd
[sink@dev ~]$ passwd 
Changing password for user sink.
Changing password for sink.
# 此处按下 Ctl+Z 与 回车
(current) UNIX password: 

[1]+  Stopped                 passwd

[sink@dev ~]$ pstree -pu | sed -n '/passwd/p'
           |                       |-bash(17492)---su(34364)---bash(34365,sink)-+-passwd(35160,root)

可以看到父进程(bash(34365,sink))的用户是sink,但是其子进程(passwd(35160,root))的用户变为了root。

4.2 /proc/* 代表的意义

进程都是在内存当中,而内存当中的数据又都是写入到 /proc/* 这个目录下的。基本上,目前主机上面的各个进程的 PID 都是以目录的型态存在于 /proc 当中。

[root@dev ~]# ll /proc/1/
total 0
dr-xr-xr-x. 2 root root 0 Nov  6 15:05 attr
-rw-r--r--. 1 root root 0 Nov  7 16:15 autogroup
-r--------. 1 root root 0 Nov  7 16:15 auxv
-r--r--r--. 1 root root 0 Nov  4 08:40 cgroup
……

重点在以下两个文件

  • cmdline:这个进程被启动的指令串
  • environ:这个进程的环境变量内容
[root@dev ~]# cat /proc/1/cmdline 
/usr/lib/systemd/systemd--switched-root--system--deserialize22

包含了指令、选项与参数,针对的是进程;那么针对系统的文件就是直接在/proc/目录下的文件啦。

4.3 查询已开启文件或已执行进程开启的文件

4.3.1 fuser:由文件找进程

fuser [-fuv] [-a|-s] [-4|-6] [-c|-m|-n space] [ -k [-i] [-M] [-w] [-SIGNAL] ] name ...

OPTIONS
    -u,--user             Append the user name of the process owner to each PID.
    -v, --verbose         列出 USER, PID, ACCESS and COMMAND.
    -a, --all             Show all files specified on the command line.
    -m,--mount            show all processes using the named filesystems or block device
    -i,--interactive      ask before killing (ignored without -k)
    -k,--kill             kill processes accessing the named file
    -SIGNAL               send this signal instead of SIGKILL
[root@dev ~]# fuser -u /bin/bash
/usr/bin/bash:        3313e(root)  3366e(root)  3367e(root)  3819e(root)  3906e(root)  4051e(root)  4249e(root)  4569e(root) 15352e(root) 17492e(root) 34365e(sink) 92679e(root) 92736e(sink) 95880e(root) 108664e(root) 108729e(sink)
[root@dev ~]# fuser -uv /bin/bash
                     USER        PID ACCESS COMMAND
/usr/bin/bash:       root       3313 ...e. (root)bash
                     root       3366 ...e. (root)pycharm-start
                     root       3367 ...e. (root)pycharm.sh
                     root       3819 ...e. (root)bash
                     ……

ACCESS所代表的意义:

  • c current directory.
  • e executable being run.
  • f open file. f is omitted in default display mode.
  • F open file for writing. F is omitted in default display mode.
  • r root directory. 顶层目录
  • m mmap'ed file or shared library.
[root@dev ~]# fuser -uv .top.log.swp 
                     USER        PID ACCESS COMMAND
/root/.top.log.swp:  root      114662 F.... (root)vi

4.3.2 lsof:由进程找文件

lsof [options] [ -- ] [names]

OPTIONS
    -a       条件参数,意思是在两边的选项都成立时才列出,即逻辑与
    -U       只列出 UNIX socket files.
    -u s     列出该使用者相关进程所开启的文件。e.g., ``sink'', or ``548,root''.不能有空格
    +D D     找出某个目录底下已经被开启的文件

    -i [i]   
    -P       禁止将端口号转换为网络文件的端口名称。
[root@dev ~]# lsof | less
# NODE 即 inode
COMMAND      PID    TID           USER   FD      TYPE             DEVICE  SIZE/OFF       NODE NAME
systemd        1                  root  cwd       DIR              253,0       246         64 /
systemd        1                  root  rtd       DIR              253,0       246         64 /
systemd        1                  root  txt       REG              253,0   1624552  101335647 /usr/lib/systemd/systemd
systemd        1                  root  mem       REG              253,0     20064    2142819 /usr/lib64/libuuid.so.1.3.0
# 既是 root 又是 socket 文件
[root@dev ~]# lsof -u root -a -U
……
# 网络文件
[root@dev ~]# lsof -u root -a -i 4 -P
COMMAND   PID USER   FD   TYPE  DEVICE SIZE/OFF NODE NAME
systemd     1 root   42u  IPv4   24643      0t0  TCP *:111 (LISTEN)
systemd     1 root   43u  IPv4   24644      0t0  UDP *:111 
sshd     1861 root    3u  IPv4   33055      0t0  TCP *:22 (LISTEN)
cupsd    1863 root   12u  IPv4   29388      0t0  TCP localhost:631 (LISTEN)
……
# 列出文件夹下被打开的文件
[root@dev ~]# lsof +d .
COMMAND      PID USER   FD   TYPE DEVICE SIZE/OFF     NODE NAME
gnome-ses   2647 root  cwd    DIR  253,0     4096 67153985 .
……

4.3.3 pidof:查找正在运行的程序的进程 ID。

pidof [options] program [program..]

OPTIONS
    -s     只返回一个 pid
    -x     同时列出该 program name 可能的 PPID 那个进程的 PID
# 普通用户也能查到 root 用户的进程
[sink@dev ~]$ pidof vi bash | xargs ps -fp
UID         PID   PPID  C STIME TTY      STAT   TIME CMD
root       3313   3303  0 Nov04 pts/0    Ss     0:00 -bash
root       3366   3313  0 Nov04 pts/0    S+     0:00 /bin/bash /usr/local/bin/pycharm-start
root       3819   3303  0 Nov04 pts/2    Ss     0:00 -bash
root     118382  17492  0 17:20 pts/8    T      0:00 vi top.log
……