进程相关命令

pstree, ps, pidof, pgrep, top, htop, glance, pmap, vmstat, dstat,kill, pkill, job, bg, fg, nohup

pstree

进程树,来自 psmisc 软件包(fuser 和 killall 也来自 psmisc ) connecting.asciidoc

1
2
3
4
5
6
7
pstree [OPTION] [ PID | USER ]

OPTION:
-p # 显示PID
-T # 不显示线程,只显示进程
-u # 显示进程所属用户
-H pid # 高亮显示指定进程及其前辈进程

ps

process state,默认显示当前终端中的进程,Linux 系统各进程的相关信息均保存在/proc/PID目录下的各个文件中。ps 显示的是进程快照,如果要动态显示实时的进程信息,可以使用 top 命令

1
ps [options]

ps 的参数有非常多,三种风格都支持

大致分以下五类,这五类是我划分的,和 man 文档不太一样,下面是常见的 option:

  1. 简单选择范围

    1
    2
    3
    a     # 显示所有终端的进程
    x # 显示不链接终端的进程
    -e # 显示所有进程,和ax显示的进程一样多,但是不如ax显示的属性多
  2. 按条件查询
    查询条件之间用逗号分割

    1
    2
    3
    4
    5
    6
    7
    8
    -p | p pidlist  # 指定pid列表
    --ppid pidlist # 显示属于pid的子进程
    -C cmdlist # 指定命令列表
    -u userlist # 指定 effective user 列表,可以写用户名或用户id
    -U userlist # 指定 real user 列表
    -g grplist # 指定effective group 列表,可以写组名或组id
    -G grplist # 指定real group 列表
    -t ttylist # 指定tty
  3. 控制输出属性

    1
    2
    3
    4
    o 属性列表  # 指定属性,属性之间用逗号分割
    u # 显示user,以及%cpu、%mem等信息,适合面向用户
    -f # 显示UID、PPID、C与STIME
    -F # 比-f多显示SZ、RSS、PSR
  4. 格式化输出

    1
    2
    3
    4
    5
    6
    f                                   # 显示进程树,相当于 --forest
    k|--sort [+|-]key[,[+|-]key[,...]] # 按照属性排序,如果多个属性,用逗号分割,属性前加-表示倒序
    -H # 显示进程层级格式,和 f 差不多

    ps aux k %cpu 等于 ps aux --sort %cpu 等于 ps aux --sort=%cpu
    ps aux k -%cpu 等于 ps aux --sort -%cpu 等于 ps aux --sort=-%cpu
  5. 显示线程

    1
    -L    # 显示线程
  6. 其他

    1
    -L   # 显示所有属性,小写的那列是属性code,大写的是属性header,`ps | head -1`输出的就是header

很多 option 是冲突的,有的冲突会报错,有的结果无意义我也算它冲突,大概有以下两种情况:

  1. 按条件查询 和 简单选择范围:我们的预期是从指定的范围内按条件查询,然后输出查询的结果,有的命令确实是这个逻辑,但是 ps 会把所有的进程和查询到的进程都输出,这样的结果是没有意义的

  2. 控制输出的属性:当多个这种类型的 option 组合在一起,如果指定的属性列表是包含关系,则正常,否则报错,例如-f 和-F 会按照-F 输出结果,但是-f 和 u 就会报错。
    简单选择范围 的 option 默认展示若干属性,它们和控制输出的属性不冲突

常用组合

常见属性

ps L可以查看所有进程属性,有 170 个,我叫它属性,实际 man 文档称之为 SPECIFIERS(说明符),o 选项可以指定 ps 输出哪些进程属性,下面是常用的进程属性:

  • user|euser:effective user,有效的用户
  • ruser:real user 真正的用户,例如普通用户 lujinkai 使用 sudo 执行命令,那 effective user 就是 lujinkai,real user 就是 root
  • fuser:
  • suser:
  • %cpu:cpu 占用率,精确到小数点后一位
  • c:cpu 占有率,精确到个位数
  • %mem:内存占有率
  • pid:进程 id,如果是线程,则是线程所在进程的 id
  • ppid:父进程 id
  • lwp|spid|tid:线程 id
  • s|state:minimal state display (one character)
  • stat:multi-character process state
  • ni|nice:nice 优先级
  • pri:priority 优先级
  • rtprio:rtprio 优先级
  • sz:物理内存大小,包括文本、数据和堆栈空间
  • psr:processor,CPU 编号,表示进程占用哪个 CPU 核心
  • vsz:虚拟内存大小,单位 k
  • rss:常驻内存大小,包括了共享库内存的大小(不同进程引用同一个库文件,那这些进程的 rss 中都包含了这个共享库的大小),单位 k
  • comm:进程名,例如:mysqld
  • command:完整命令,例如:/usr/local/mysql/bin/mysqld --basedir=/usr/local/mysql --datadir=/data/mysql --plugin-dir
  • time|cputiime:进程占用 CPU 的累计时间
  • lstart:开始时间
  • etime:运行时间
  • stime:启动进程的时间

进程状态码

1
2
3
4
5
6
7
8
9
D    # 睡眠状态,不可中断 (通常是IO)
R # 可执行状态,进程处于运行或就绪状态 (on run queue)
S # 睡眠状态(sleeping) 可中断 (waiting for an event to complete)
T # stopped by job control signal
t # stopped by debugger during the tracing
W # paging (not valid since the 2.6.xx kernel)
X # 退出状态,进程即将被销毁 (should never be seen)
Z # 退出状态(zombie),终止但是未被父进程收回,进程成为僵尸进程
I # Idle kernel thread,CentOS 8 新特性

对于 BSD 风格,stat 还会显示下面的状态码:

1
2
3
4
5
6
<    # 高优先级(对其他用户不好)
N # 低优先级(对其他用户很好)
L # 内存分页并带锁(用于实时和自定义IO)
s # is a session leader
l # 多线程 (using CLONE_THREAD, like NPTL pthreads do)
+ # 在前台进程组中,前台进程

prtstat

查看进程详细信息,ps 适合查找进程,确定 pid,然后使用 prtstat 查看详细信息。

1
2
3
prtstat [options] PID ...

-r # raw格式显示
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
[root@4710419222 ~]# prtstat 24954
Process: php-fpm State: S (sleeping)
CPU#: 0 TTY: 0:0 Threads: 1
Process, Group and Session IDs
Process ID: 24954 Parent ID: 24953
Group ID: 24953 Session ID: 24953
T Group ID: -1

Page Faults
This Process (minor major): 8195 0
Child Processes (minor major): 0 0
CPU Times
This Process (user system guest blkio): 0.15 0.02 0.00 0.00
Child processes (user system guest): 0.00 0.00 0.00
Memory
Vsize: 185 MB
RSS: 17 MB RSS Limit: 18446744073709 MB
Code Start: 0x400000 Code Stop: 0xeab9c1
Stack Start: 0x7fff3beae6e0
Stack Pointer (ESP): 0x7fff3beae198 Inst Pointer (EIP): 0x7f67ad7f8840
Scheduling
Policy: normal
Nice: 0 RT Priority: 0 (non RT)
[root@4710419222 ~]#
[root@4710419222 ~]#
[root@4710419222 ~]# prtstat -r 24954
pid: 24954 comm: php-fpm
state: S ppid: 24953
pgrp: 24953 session: 24953
tty_nr: 0 tpgid: -1
flags: 402140 minflt: 8195
cminflt: 0 majflt: 0
cmajflt: 0 utime: 15
stime: 2 cutime: 0
cstime: 0 priority: 20
nice: 0 num_threads: 1
itrealvalue: 0 starttime: 2798685522
vsize: 185421824 rss: 4316
rsslim: 18446744073709551615 startcode: 4194304
endcode: 15382977 startstack: 140734198638304
kstkesp: 7FFF3BEAE198 kstkeip: 7F67AD7F8840
wchan: 18446744071584583552 nswap: 0
cnswap: 18446744071584583552 exit_signal: 17
processor: 0 rt_priority: 0
policy: 0 delayaccr_blkio_ticks: 0
guest_time: 0 cguest_time: 0

设置和调整进程优先级

静态优先级:在创建进程时确定的,且在进程的整个运行期间保持不变,静态优先级的范围是 100 到 139

nice

进程默认启动时的 nice 值是 0,对应 的优先级是 120,只有根用户才能降低 nice 值

1
2
3
nice [OPTION] [COMMAND [ARG]...]

-n # 指定优先级, -20到19

以指定的优先级来启动进程:

1
[root@centos8 ~]#nice -n -10 ping 127.0.0.1

renice

调整正在执行中的进程的优先级

1
[root@centos8 ~]#renice -n -20 2118

搜索进程

按条件搜索进程:

  • ps options | grep 'pattern' 最灵活
  • pgrep 按预定义的模式
  • pidof 按确切的程序名称查看 pid

pgrep

顾名思义,过滤进程

1
2
3
4
5
6
7
8
 pgrep [options] <pattern>

-u uidlist # effective user
-U uidlist # real user
-t terminal # 与指定终端相关的进程
-l # 显示进程名
-a # 显示完整格式的进程名
-P pid # 显示指定进程的子进程

pidof

1
2
3
pidof [options] [program [...]]

-x # 按脚本名称查找pid
1
2
[root@centos8 ~]#pidof -x ping.sh
19035

uptime 和 w

uptime 显示:当前时间、系统启动时间、当前在线人数、系统负载(1、5、15 分钟的平均负载,一般不会超过 1,超过 5 时建议警报)

1
2
[root@4710419222 ~]# uptime
22:04:28 up 325 days, 4:05, 2 users, load average: 0.01, 0.04, 0.05

w 除了显示 uptime 显示的内容外,还可以在线人员的信息

1
2
3
4
5
[root@4710419222 ~]# w
22:07:46 up 325 days, 4:08, 2 users, load average: 0.05, 0.03, 0.05
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
root pts/1 39.164.140.134 20:17 3:14 0.49s 0.49s -bash
root pts/4 39.164.140.134 21:17 2.00s 0.04s 0.00s w

mpstat

来自于 sysstat 包,显示 CPU 相关统计

1
2
3
mpstat [options] [ interval [ count ]

-p # 指定查看的cpu核心
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
lujinkai@Z510:~$ mpstat
Linux 5.4.0-46-generic (Z510) 09/03/20 _x86_64_ (4 CPU)

22:15:39 CPU %usr %nice %sys %iowait %irq %soft %steal %guest %gnice %idle
22:15:39 all 10.43 0.51 3.06 0.07 0.00 0.86 0.00 0.00 0.00 85.08
lujinkai@Z510:~$ mpstat 1 3
Linux 5.4.0-46-generic (Z510) 09/03/20 _x86_64_ (4 CPU)

22:15:45 CPU %usr %nice %sys %iowait %irq %soft %steal %guest %gnice %idle
22:15:46 all 10.97 0.00 3.83 0.00 0.00 0.51 0.00 0.00 0.00 84.69
22:15:47 all 6.72 0.00 3.98 0.00 0.00 1.99 0.00 0.00 0.00 87.31
22:15:48 all 6.08 0.00 3.54 0.00 0.00 1.27 0.00 0.00 0.00 89.11
Average: all 7.91 0.00 3.78 0.00 0.00 1.26 0.00 0.00 0.00 87.05
lujinkai@Z510:~$ mpstat -P 0 1 2
Linux 5.4.0-46-generic (Z510) 09/03/20 _x86_64_ (4 CPU)

22:15:52 CPU %usr %nice %sys %iowait %irq %soft %steal %guest %gnice %idle
22:15:53 0 7.22 0.00 5.15 1.03 0.00 0.00 0.00 0.00 0.00 86.60

22:15:53 CPU %usr %nice %sys %iowait %irq %soft %steal %guest %gnice %idle
22:15:54 0 7.14 0.00 7.14 0.00 0.00 1.02 0.00 0.00 0.00 84.69

Average: CPU %usr %nice %sys %iowait %irq %soft %steal %guest %gnice %idle
Average: 0 7.18 0.00 6.15 0.51 0.00 0.51 0.00 0.00 0.00 85.64

top

查看进程实时状态

htop

top 的升级版

cpu4 核 4 线程和 4 核 8 线程的区别:

1
4核 就是有4个物理核心,4线程 就是一个核心对应一个线程,8线程就是两个线程对应一个核心,是intel使用超线程技术,把一个物理核心模拟成两个逻辑核心。所以任务管理器或者htop会显示会显示出8张CPU表

关于 PR、NI、PRI:

1
2
3
PR:priority 优先级,系统调节
NI:nice 反应一个进程“优先级”状态的值,其取值范围是-20至19,一共40个级别。这个值越小,表示进程“优先级”越高。就像人一样,越nice的人,抢占资源的能力就越差,而越不nice的人抢占能力就越强。这个值用户可以调节
PRI:PR + NI,PRI才是进程最终的优先级,用户可以通过调节NI来影响它

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
1-8             # cpu每个核心负载
Mem # 物理内存,共计7.51G,已用4.95G
Swp # 交换内存,共计2G,已使用4M
Tasks # 进程、线程、正在运行的进程,当前系统有268个进程,910个线程,正在运行的进程有1个
Load average # 系统1分钟、5分钟、10分钟的平均负载情况
Uptime # 系统运行时间

PID # 进程id
USER # 运行此进程的用户
PRI # 运行此进程的优先级
NI # 进程的优先级别值,默认的为0,可以进行调整
VIRT # 进程占用的虚拟内存
RES # 进程当前使用的内存大小,但不包括swap out,包含其他进程的共享,如果申请100m,实际只使用10m,它只增长10m,与virt相反
SHR # 进程占用的共享内存值,计算某个进程所占用的物理内存大小公式:RES - SHRS
# 进程的状态,其中S表示休眠,R表示正在运行,Z表示僵死状态,N表示该进程优先值是负数
O # 进程正在处理器运行
S # 睡眠状态(sleeping) 可中断
D # 睡眠状态(disk sleep),有时候也叫不可中断睡眠状态,在这个状态的进程通常会等待I/O的结束
R # 可执行状态(runable)Running or runnable (on run queue) 进程处于运行或就绪状态
I # 空闲状态(idle)
Z # 退出状态(zombie)进程成为僵尸进程
T # 暂停状态或跟踪状态(stoped or traced)
B # 进程正在等待更多的内存页
X # 退出状态,进程即将被销毁
%CPU # 该进程占用的CPU使用率
%MEM # 该进程占用的物理内存和总内存的百分比
TIME+ # 该进程启动后占用的总的CPU时间
COMMAND # 进程启动的启动命令名称

VIRT:进程占用的虚拟内存,这个虚拟内存和 swp 没有关系,是进程“需要的”虚拟内存大小,包括进程使用的库,代码,数据等。

假如进程申请 100m 的内存,但实际上只使用 了 10m,那么它会增长 100m,而不是实际的使用量

现代操作系统里面分配虚拟地址空间操作不同于分配物理内存。在 64 位操作系统上,可用的最大虚拟地址空间有 16EB,即大概 180 亿 GB。那么在一台只有 16G 的物理内存的机器上,我也能要求获得 4TB 的地址空间以备将来使用。例如:

1
void *mem = mmap(0, 4ul * 1024ul * 1024ul * 1024ul * 1024ul, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE, -1, 0);

当使用 mmap 并设置 MAP_NORESERVE 标志时,并不会要求实际的物理内存和 swap 空间存在。所以上述代码可以在 top 中看到使用了 4096g 的 VIRT 虚拟内存,这当然是不可能的,它只是表示使用了 4096GB 的地址空间而已

一般来说不用太在意 VIRT 太高,因为你有 16EB 的空间可以使用

free

显示内存使用情况

1
2
3
4
5
6
7
8
9
10
free [options]

-b #以字节为单位
-m #以MB为单位
-g #以GB为单位
-h #易读格式
-o #不显示-/+buffers/cache行
-t #显示RAM + swap的总和
-s n #刷新间隔为n秒
-c n #刷新n次后即退出

pmap

进程对应的内存映射

vmstat

虚拟内存信息

iostat

统计 CPU 和设备 IO 信息

dstat

系统资源统计

iotop

监视磁盘 I/O

iftop

显示网络带宽使用情况

iftop 和 nethogs

nload

查看网络实时吞吐量

glances

综合监控工具

lsof

查看进程打开文件

cockpit

CentOS8 新特性

kill

信号发送

作业管理

nohup

no hang up,不挂断的意思,如果当前 terminal 关闭了,命令就转为后台继续运行

nohup 和 & 的区别:

如果不是通过 exit 退出 terminal,而是点击 × 强行关闭 terminal,通过 & 进入后台的命令会被杀死,而通过 nohup 会将命令转后台继续运行,所以二者通常搭配一起使用

范例:

1
2
[root@elk2-ljk bin]$nohup ./cerebro >/dev/null 2>&1 &
[1] 4149

screen

  • 创建新会话: screen -S <session-name>
  • 加入会话:screen -x <session-name>
  • 退出并关闭会话:exit
  • 剥离当前会话:ctrl + a,d
  • 显示所有已经打开的会话:screen -ls
  • 恢复某会话:screen -r <session-name>

关于 -x-r : -x 是加入会话,多个终端都可以加入,-r 是恢复会话,当一个终端恢复会话,其他终端就无法恢复,只能加入

1
2
3
4
5
screen -S new
# ctrl + a,d
screen -r new
# 另起一个终端
screen -x new

tmux

Tmux 是一个终端复用器(terminal multiplexer),类似 screen,但是更易用,也更强大

tmux 好像不能共享会话

  • 新建会话:tmux new -s <session-name>

  • 查看所有会话:tmux ls

    1
    2
    3
    4
    [root@centos7 lujinkai]# tmux ls
    jin: 1 windows (created Sat Jul 25 13:51:23 2020) [80x45] (attached) #当前所处的会话是jin
    kai: 1 windows (created Sat Jul 25 13:51:34 2020) [80x45]
    lu: 1 windows (created Sat Jul 25 13:49:33 2020) [80x45]
  • 退出会话:exit

  • 分离会话:ctrl + b d 或者tmux detach

  • 接入会话:tmux attach -t <session-name> 用于重新接入某个已经存在的会话。

  • 切换会话:tmux switch -t <session-name>

  • 杀死会话:tmux kill-session -t <session-name>

并行运行