Linux常用命令--进程管理

摘要

  • 本文介绍Linux进程管理等相关命令

  • 本文基于CentOS8(x86_64)

ps :查看进程

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
# 与top命令类似,可以查看进程信息
$ ps -aux
-a:所有用户
-x:没有控制终端的
-u:显示用户名和启动时间
# 根据关键字过滤
$ ps -aux | grep nginx

$ ps -ef
-e:显示所有进程,包括用户和没有控制终端
-f:显示所有信息

# 查看线程,相同PID表示的是同一个进程启动的线程
$ ps -eLf
-L:显示线程

# 查看进程优先级 NI
$ ps -el

# 查看进程运行在第几个cpu逻辑核心上
$ ps -eo psr,user,pid,ppid,pri,ni,pgid,command | grep nginx
psr:cpu逻辑核号
pri :默认19,优先级 0~99,越大优先级越高,pri(new) = pri(old) + nice
ni :默认0,影响优先级的因子 -20~19,越小优先级越高,改变nice值可以改变pri
pgid :进程组id,等同于 pgrp
# 绑定PID为10288的进程到第一块CPU,这样该进程就不会占用其它的CPU资源了
$ taskset -cp 1 10288

# 按pid排序
$ ps -aux --sort pid
# 按用户排序
$ ps -aux --sort user

# 说明:
USER:进程的执行用户
PID:进程号
PPID:父进程号
TTY:进程启动的终端
STAT:进程的当前状态,S:休眠 D:不可中断的休眠 R:运行 Z:僵死 T:停止 I:空闲内核线程
NI:进程优先级
TIME:进程自启动以来占用CPU的总时间
CMD/COMMAND:执行的命令
%CPU:占用CPU时间和总时间的百分比
%MEM:占用内存与系统内存总量的百分比

pstree :树状查看进行信息

1
2
3
4
5
6
# 折叠展示,只展示父进程和子进程的数量
$ pstree
# 展开所有子进程,并显示完整命令
$ pstree -a
# 展开所有子进程,并显示PID
$ pstree -p

kill :终止进程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# 正常关闭进程
kill 进程号
# 强行关闭,遇到进程不能正常关闭时使用
kill -9 进程号
# 查看所有信号
kill -l

# 杀死进程名称所关联的全部进程
killall 进程名称
killall -9 进程名称

# 杀死进程名称所关联的全部进程,同killall
pkill 进程名称
pkill -9 进程名称

# 查找服务的进程号
pgrep 进程名称 : 效果同 ps -aux | grep 进程名 | grep -v grep| awk '{print $2}'
# 终止进程名称为mysql的全部进程
pgrep mysql | xargs kill -s 9

pgrep -f 匹配字符串 :其表示查找所有包含‘匹配字符串’的进程
#比如:查询 elasticsearch
pgrep elasticsearch # 此时查询不出进程Id,因为elasticsearch的进程是java
pgrep -f elasticsearch # 可以查询出进程Id,因为只要进程完整路径中包含elasticsearch就行

信号量

  • 通过kill -l可以查看所有信号的编号和名称
信号编号 信号名称 说明
1 SIGHUP 挂起信号,通常用于通知进程终端断开或重新加载配置。
2 SIGINT 中断信号,通常由用户通过键盘 (Ctrl+C) 发送,用于中断一个进程。
3 SIGQUIT 退出信号,通常由键盘 (Ctrl+\) 发送,要求进程生成核心转储并退出。
4 SIGILL 非法指令信号,表示进程执行了非法或未定义的机器指令。
5 SIGTRAP 陷阱信号,通常用于调试程序(如断点异常)。
6 SIGABRT 异常终止信号,进程调用 abort() 函数时触发。
7 SIGBUS 总线错误信号,通常由于未对齐的内存访问引发。
8 SIGFPE 浮点异常信号,例如除零或溢出。
9 SIGKILL 强制终止信号,无法被捕获或忽略,立即终止进程。
10 SIGUSR1 用户自定义信号 1,用户或应用程序自定义用途。
11 SIGSEGV 段错误信号,表示进程访问了非法的内存地址。
12 SIGUSR2 用户自定义信号 2,用户或应用程序自定义用途。
13 SIGPIPE 管道破裂信号,通常在写入一个已关闭的管道或套接字时触发。
14 SIGALRM 定时器信号,由 alarm() 函数触发,用于定时操作。
15 SIGTERM 终止信号,允许进程执行清理操作后终止。这个也是缺省的信号。
16 SIGSTKFLT 堆栈错误信号,主要用于硬件相关的堆栈操作(极少使用)。
17 SIGCHLD 子进程状态改变信号,当子进程退出或停止时触发。
18 SIGCONT 继续信号,用于恢复被暂停的进程。
19 SIGSTOP 暂停信号,无法被捕获或忽略,立即暂停进程。
20 SIGTSTP 终端暂停信号,通常通过键盘 (Ctrl+Z) 发送。
21 SIGTTIN 后台进程尝试从终端读取输入时触发。
22 SIGTTOU 后台进程尝试向终端写入输出时触发。
23 SIGURG 紧急条件信号,通常用于套接字通信中的紧急数据。
24 SIGXCPU 超过 CPU 时间限制信号。
25 SIGXFSZ 超过文件大小限制信号。
26 SIGVTALRM 虚拟定时器信号,由 setitimer() 触发,用于进程执行时间的计时。
27 SIGPROF 统计定时器信号,用于程序性能分析。
28 SIGWINCH 窗口大小改变信号,终端窗口调整时触发。
29 SIGIO I/O 可用信号,表示文件描述符可用。
30 SIGPWR 电源故障信号。
31 SIGSYS 无效的系统调用信号。
  • 从 SIGRTMIN(34)到 SIGRTMAX(64)的信号是实时信号,供用户或应用程序使用,具有更高的优先级和灵活性。

  • 使用时,可以通过数字或名称来指定信号,例如 kill -9kill -SIGKILL,当然也支持去掉SIG的简称,例如 kill -KILL

  • 咋一看有很多,但实际上我们日常通过键盘能操作的就几个。

      1. SIGHUP:挂起信号,通常用于通知进程终端断开或重新加载配置。
    1
    2
    3
    4
    # 重新加载nginx配置文件
    kill -HUP `cat /var/run/nginx.pid`
    # 或者
    sudo systemctl reload nginx
      1. SIGINT:中断信号,通常由用户通过键盘 (Ctrl+C) 发送,用于中断一个进程。
      1. SIGQUIT:退出信号,通常由键盘 (Ctrl+\) 发送,要求进程生成核心转储并退出。
      1. SIGKILL:强制终止信号,无法被捕获或忽略,立即终止进程。
    1
    2
    # 强制终止进程
    kill -9 `cat /var/run/nginx.pid`
      1. SIGTERM:用于优雅的终止进程,通常由用户或应用程序发送,用于通知进程进行清理操作。这个也是缺省的信号。
    1
    2
    3
    4
    # 终止进程
    kill -TERM `cat /var/run/nginx.pid`
    # 或者
    kill `cat /var/run/nginx.pid`

进程的挂起和恢复

1
2
3
4
5
6
7
8
9
10
11
12
13
ctrl+c :终止

ctrl+z :挂起,暂停

bg num :转到后台继续运行

fg num :从后台恢复到前台继续运行

jobs :查看被挂起或正在后台运行的进程,会显示编号num

commond & :后台运行,只在当前终端下有效

nohup commond & :后台执行,退出终端依然继续执行

进程运行优先级

  • 进程优先级是 PRI(top中的PR),其表示程序被 CPU 执行的先后顺序,此值越小进程的优先级别越高

  • PRI 值不是 Nice 值,但是 Nice 值会影响优先级,PRI(new) = PRI(old) + nice,所以我们调整 Nice 值,就可以改变进程的优先级

  • linux下的进程调度优先级 Nice 是从 -20 到 19 ,一共 40 个级别,数字越大,表示进程的优先级越低。默认时候,进程的调度优先级是0。

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
# 指定命令的运行优先级
nice -n commond
# 改变一个正在运行的进程的优先级
renice n pid
# 改变进程组内全部进程的优先级
renice n -g pid
# 说明
n :取值范围(-20,19),越小优先级越高

# 示例
# 默认启动nginx
$ nginx
# 查看优先级,可以看到此时默认优先级是0
ps -eo pgid,user,pid,pri,ni,command | grep nginx | grep -v grep
23348 root 23348 19 0 nginx: master process nginx
23348 nginx 23349 19 0 nginx: worker process
23348 nginx 23350 19 0 nginx: worker process
# 终止nginx进程
$ pkill nginx
# 重新指定优先级启动,指定优先级为10
$ nice -10 nginx
# 查看优先级,可以看到此时默认优先级是10
$ ps -eo pgid,user,pid,pri,ni,command | grep nginx | grep -v grep
23388 root 23388 9 10 nginx: master process nginx
23388 nginx 23389 9 10 nginx: worker process
23388 nginx 23390 9 10 nginx: worker process
# 改变运行中的nginx的优先级为-10,此时只会改变master的优先级
$ renice -10 23388
23388 (进程 ID) 旧优先级为 10,新优先级为 -10
$ ps -eo pgid,user,pid,pri,ni,command | grep nginx | grep -v grep
23388 root 23388 29 -10 nginx: master process nginx
23388 nginx 23389 9 10 nginx: worker process
23388 nginx 23390 9 10 nginx: worker process

# 改变运行中的nginx的优先级为-10,此时只会改变master的优先级
$ renice -10 -g 23388
23388 (进程组 ID) 旧优先级为 -10,新优先级为 -10
$ ps -eo pgid,user,pid,pri,ni,command | grep nginx | grep -v grep
23388 root 23388 29 -10 nginx: master process nginx
23388 nginx 23389 29 -10 nginx: worker process
23388 nginx 23390 29 -10 nginx: worker process

at :执行一次的计划任务

  • /var/spool/at:at任务存放在该目录下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 启动at服务
systemctl start atd

# 今天10:46执行 test.sh
at -f test.sh 10:46
# 时间格式:
5:30pm :今天下午5点30分
17:30 :今天下午5点30分
17:30 today :今天下午5点30分
now +3 hours :3小时后
now +180 minutes :3小时后
17:30 23.2.28 :2023年2月28日下午5点30分

# 查看当前at队列,显示编号num
at -l ==== atq

# 删除指定编号的任务
at -d num ==== atrm num
  • 用户限制:
    /etc/at.allow :如果文件存在,则只有此文件中列出的用户可以使用at命令
    /etc/at.deny :如果文件存在,则此文件中列出的用户不可以使用at命令
    如果以上两个文件都不存在,则只有root用户可以使用at命令
    如果以上两个文件都存在,但是都为空,则所有用户都可以使用at命令

crontab :周期性计划任务

  • systemctl start crond :启动cron服务,默认启动

  • crontab -l :显示当前用户下的计划任务

  • crontab -e :编辑当前用户下的计划任务

  • /var/spool/cron :计划任务保存在该路径下

  • /etc/cron.allow/etc/cron.deny :用户限制,规则同 at

  • 格式:分钟[0~59] 小时[0~23] 日期[1~31] 月份[1~12] 星期[0~6] commands

1
2
3
4
5
6
7
8
9
10
11
# 每5分钟执行一次
*/5 * * * * command

# 每天2点执行一次
0 2 * * * command

# 每天2、3、4、5点各执行一次
0 2-5 * * * command

# 周一至周五每天9点和18点各执行一次
0 9,18 * * 1-5 command

systemctl :服务管理

  • centOS7以后使用systemd进行服务管理,其命令接口为systemctl

  • systemctl兼容了service,即systemctl也会去/etc/init.d目录下,查看、执行相关程序

  • 如下centOS6及之前的服务启动方式,centOS7及之后仍然可以通过这种方式管理服务,实际上会重定向到systemctl命令

1
2
3
4
service redis start
service redis stop
service redis restart
service redis status
  • systemd的服务配置放在目录/usr/lib/systemd/system (Centos)/etc/systemd/system (Ubuntu)

  • 配置目录下有多种类型文件.mount,.service,.target,.socket,.timer等等

    • 不同的文件类型代表不同的资源,统称为 Unit(单位),Unit 一共分成12种类型
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    Service unit:系统服务
    Target unit:多个 Unit 构成的一个组
    Device Unit:硬件设备
    Mount Unit:文件系统的挂载点
    Automount Unit:自动挂载点
    Path Unit:文件或路径
    Scope Unit:不是由 Systemd 启动的外部进程
    Slice Unit:进程组
    Snapshot Unit:Systemd 快照,可以切回某个快照
    Socket Unit:进程间通信的 socket
    Swap Unit:swap 文件
    Timer Unit:定时器
    • 重点学习.service文件,其定义了一个服务,分为[Unit],[Service],[Install]三个小节
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    [Unit]
    Description:描述,
    After:在哪些服务启动后才启动
    ConditionPathExists: 执行条件
    [Service]
    EnvironmentFile:变量所在文件
    ExecStart: 执行启动脚本
    Restart: fail时重启
    [Install]
    Alias:服务别名
    WangtedBy: 多用户模式下需要的
  • 查看服务

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
# 列出当前已经加载启动的 unit,如果添加 -all 选项会同时列出没有启动的 unit
systemctl # ==== systemctl list-units
# 加载后有几种情况
# loaded active running 加载文件成功,启动成功,正在运行
# loaded active exited 加载文件成功,启动成功,运行一次正常退出
# loaded active waiting 加载文件成功,启动成功,正在运行,不过还在等待其它事件才能继续处理
# loaded failed failed 加载文件成功,启动失败,运行失败

systemctl -all
# 会多几个状态
# not-found inactive dead 加载文件失败[没找到文件]
# loaded inactive dead 加载文件成功 但没有设置问开机启动,所以没有运行过

# 只查看服务类型为service的服务
systemctl --type service
systemctl list-units --type=service -all

# 查看是否有安装图形化环境,这里要注意,即便运行级别为5(graphical.target),如果没有安装图形化环境则会降级到命令行界面
systemctl --type=service | grep -E '(gdm|kdm|lightdm)'
# 或者
systemctl status gdm kdm lightdm


# 根据 /lib/systemd/system/ 目录内的文件列出所有的服务及其当前的状态,如是否开机启动等等
systemctl list-unit-files
# 状态类型
# enabled 设置为开机启动
# disabled 没有设置为开机启动
# masked 注销状态,此时不能通过systemctl进行启动,需要先取消注销状态
# static 该配置文件没有[Install]部分(无法执行),只能作为其他配置文件的依赖

# 只列出设置为开机启动的项
systemctl list-unit-files | grep enabled

# 只列出service
systemctl list-unit-files --type service

# 如果发现某个 服务 不工作,可以查看是否有 服务 加载失败
systemctl --failed
  • service :系统服务

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
# 启动redis服务
systemctl start redis
# 重新启动redis服务
systemctl restart redis
# 关闭redis服务
systemctl stop redis
# 不关闭redis的情况下重新加载配置文件,让新的设置生效
systemctl reload redis
# 加入开机自启动
systemctl enable redis
# 关闭开机自启动
systemctl disable redis
# 查看redis服务状态
systemctl status redis
# 目前有没有正在运行中
systemctl is-active redis
# 开机时有没有默认要启用
systemctl is-enabled redis
# 是否启动失败
systemctl is-failed redis
# 列出 redis服务 的配置
systemctl show redis
# 注销 redis服务 ,注销后就无法启动
systemctl mask redis
# 取消 redis服务 的注销
systemctl unmask redis

# 在脚本中判断服务是否启动
if systemctl --quiet is-active $serviceName
then
echo "$serviceName is running"
# do something,for example: stop $serviceName
systemctl stop $serviceName
else
echo "$serviceName is not running"
fi

小贴士

1
2
3
4
5
6
7
8
9
10
11
# 查看系统启动耗时
$ systemd-analyze

# 查看每个服务的启动耗时
$ systemd-analyze blame

# 显示瀑布状的启动过程流
$ systemd-analyze critical-chain

# 显示指定服务的启动流
$ systemd-analyze critical-chain sshd.service
  • target :类似于运行级别,支持多个target同时启动。target其实是多个unit的组合,系统启动说白了就是启动多个unit

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

# 只查看服务类型为target的服务
systemctl list-units --type=target -all
# 取得目前缺省的 target
systemctl get-default
# 几个常用的 target。
graphical.target:多人模式,支持图形和命令行两种登录,对应之前的3,5级别。
multi-user.target:多人模式,只支持命令行登录,对应3级别!
rescue.target:单人模式,对应1级别,在无法使用 root 登陆的情况下,systemd 在开机时会多加一个额外的临时系统,与你原本的系统无关。这时你可以取得 root 的权限来维护你的系统。
emergency.target:单人模式,不过系统进入后根目录是只读的,紧急处理系统的错误,在无法使用 rescue.target 时,可以尝试使用这种模式!

# 设置缺省的 target
systemctl set-default multi-user.target
# 切换到指定的 target
systemctl isolate multi-user.target

# 查看依赖关系,查看 multi-user.target 依赖哪些服务,默认树形展示
systemctl list-dependencies multi-user.target
# 查看依赖关系,查看 multi-user.target 依赖哪些服务,--plain:去掉了树形结构的视觉效果,将输出更改为平面列表。这样可以方便地用其他命令(例如grep)进行进一步的处理。--all:这个选项表示显示所有依赖,包括那些因某种原因没有启动或无法访问的依赖项。
systemctl list-dependencies --all --plain multi-user.target

# 反向查看依赖关系, --reverse 选项查看 multi-user.target 被谁使用
systemctl list-dependencies multi-user.target --reverse

小贴士

  • 1.systemd 主配置文件 /etc/systemd/system.conf
  • 2.开机会先加载 /etc/systemd/system/default.target
  • 3.所有的 servicetarget 都在 /usr/lib/systemd/system/目录下
  • 4./etc/systemd/system/defaut.target 是一个软连接,软连接到了/usr/lib/systemd/system/multi-user.target,它会加载/usr/lib/systemd/system/multi-user.target.wants下面的service
  • 5.查看一个service属于哪个target,需要查看具体的service文件,如:cat /usr/lib/systemd/system/sshd.service,看里面[install]部分

chkconfig :设置系统服务在哪些运行级别下开机启动

  • centOS7之后不再使用这种方式,而是使用systemctl,但是仍然可以在/etc/init.d目录下创建管理脚本,然后通过chkconfig进行管理

1
2
3
4
5
6
chkconfig --list :查看全部系统服务的运行级别
chkconfig --list sshd :查看sshd系统服务的运行级别
chkconfig --level 2345 sshd on :修改sshd服务的运行级别为2345都启动,on/off
chkconfig sshd on :默认就是开启2345运行级别
chkconfig --add nginx :添加服务到管理列表中,需要在`/etc/init.d`目录下有对应的nginx文件
chkconfig --del nginx :从管理列表中删除

ntsysv :通过界面设置服务是否开机启动

  • centOS7之后不再使用这种方式,而是使用systemctl,但是仍然可以使用其管理当前运行级别下的服务

  • 运行命令后会弹出设置界面,服务前面有*号的表示开机启动,使用空格修改,Tab键进行跳转

1
2
3
4
5
6
# 修改当前的运行级别下的服务
ntsysv
# 修改3运行级别下的服务
ntsysv --level 3
# 同时修改3和5运行级别下的服务
ntsysv --level 35

Linux运行级别
0:系统关机模式,系统默认运行级别不能设置为0,否则无法正常启动系统
1:单用户模式,也称为救援模式,root权限,用于系统维护,禁止远程登陆,类似Windows下的安全模式登录。
2:无网络支持的多用户模式
3:有网络支持的多用户模式(文本模式,工作中最常使用的模式)
4:保留,未使用
5:有网络支持的图形化模式,支持多用户模式,登陆后进入图形GUI模式或GNOME、KDE图形化界面,如X Window系统。
6:重启模式,重新引导系统,即重启

运行级别切换

1
2
3
4
5
6
7
8
9
# 查看当前的运行级别,输出结果为: 上一次运行级别 当前运行级别
runlevel

# 切换运行级别
init 0 ==== systemctl isolate poweroff.target ==== systemctl poweroff
init 1 ==== systemctl isolate rescue.target
init 3 ==== systemctl isolate multi-user.target
init 5 ==== systemctl isolate graphical.target
init 6 ==== systemctl isolate reboot.target ==== systemctl reboot

fuser :可以显示出当前哪个程序在使用磁盘上的某个文件、挂载点、甚至网络端口,并给出程序进程的详细信息

  • fuser通常被用在诊断系统的resource busy问题,通常是在你希望umount指定的挂载点得时候遇到

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 查看哪个进程在访问/mnt目录
fuser /mnt :只显示PID和权限
fuser -u /mnt :-u,在每个PID后面添加进程拥有者的用户名称
fuser -v /mnt :-v,显示详细信息,包含PID,USER,COMMAND等许多域

# 把访问mnt目录的进程杀掉
fuser -kv /mnt :-k,杀掉进程
fuser -kvi /mnt :-i,会询问你是否杀掉对应的进程

# 查看80端口被哪个进程占用
fuser -n tcp 80 :-n,指定协议和端口
fuser 80/tcp :不加-n,需要这样指定协议和端口

fuser -un tcp 80
fuser -u 80/tcp

fuser -vn tcp 80
fuser -v 80/tcp

# 杀掉占用80端口的进程
fuser -kvn tcp 80
fuser -kvin tcp 80
fuser -kvi 80/tcp

查看进程启动时的环境变量

  • 所有启动的进程都会在/proc/下创建以其进程IP命名的文件夹,其下为与当前进程相关为文件,其中environ中的没人就是进程启动时的环境变量,比如我们查看elasticsearch的进程

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
$ pgrep -f elasticsearch
4603

$ sudo more /proc/4603/environ
XDG_SESSION_ID=c2SIZE=1000usersql8/bin:/usr/local/soft/redis-5.0.14/src:/home/ec2-user/.local/bin:/home/ec2-user/binvar/spool/mail/ec2-usergnoredupsME=ec2-user

# 上面看着比较混乱,因为每个环境变量之间是通过'\0'分隔的,我们将其替换为'\n'
# 在/proc/[PID]/environ文件中,进程的环境变量是以null字符分隔的,即以'\0'(空字符)结尾
$ sudo more /proc/4603/environ | tr '\0' '\n'
XDG_SESSION_ID=c2
HOSTNAME=ip-10-250-0-214.cn-northwest-1.compute.internal
SHELL=/bin/bash
HISTSIZE=1000
OLDPWD=/home/ec2-user
ES_JAVA_HOME=/usr/local/soft/elasticsearch-7.17.6/jdk
USER=ec2-user
PATH=/usr/local/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/usr/local/bin:/usr/local/soft/mysql8/bin:/usr/local/soft/redis-5.0.14/src:/home/ec2-user/.local/bin:/home/ec2-user/bin
MAIL=/var/spool/mail/ec2-user
PWD=/usr/local/soft/elasticsearch-7.17.6
LANG=en_US.UTF-8
HISTCONTROL=ignoredups
HOME=/home/ec2-user
SHLVL=1
LIBFFI_TMPDIR=/tmp/elasticsearch-4722185969271784034
LOGNAME=ec2-user
LESSOPEN=||/usr/bin/lesspipe.sh %s
XDG_RUNTIME_DIR=/run/user/1000