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就行

进程的挂起和恢复

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
# 列出当前已经加载启动的 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

# 根据 /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
24
25
26

# 只查看服务类型为target的服务
systemctl list-units --type=target -all
# 取得目前缺省的 target
systemctl get-default :multi-user.target

# 几个常用的 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