Linux进程管理

什么是进程

Linux系统当中:【触发任何一个事件时,系统都会将它定义成为一个进程,并且给予这个进程一个ID,称为PID,同时根据触发这个进程的用户与相关属性关系,给予这个PID一组有效的权限设置】。从此以后,这个PID能够在系统上面执行的操作就与这个PID的权限有关

进程与程序

进程:通过【执行一个程序或命令】就可以触发一个事件而获取一个PID。

程序:系统只认识二进制文件,因此在让系统工作时,需要调用一个二进制文件,也就是程序

每个进程都有三组权限,分别是读(r)、写(w)、执行(x)的权限。【对不同用户身份执行同一个程序时,系统赋予的权限也会有所不同】。

举个例子,我们可以使用touch命令来创建一个空文件。当root用户执行touch命令时,它的权限是UID/GID=0/0;而当dmtsai用户(UID/GID=501/501)执行touch命令时,它的权限与root用户是不同的

如下图

程序一般存放在物理磁盘中,用户执行后会被加载到内存中成为一个进程。为了让操作系统能够管理这个进程,进程会具有执行者的权限属性和其他参数,以及进程所需的脚本或数据等。最后会给进程分配一个PID。操作系统通过这个PID来判断进程是否有执行权限

image-20240323125127163

当登陆并执行bash时,系统已经给了我们一个PID,这个PID就是根据登录者的UID/GID(/etc/passwd)而来。如下图

/binlbash是一个程序,当csq登录后,它获取一个PID为2234的进程,这个进程的User/Group 都是csq而当这个进程执行其他作业时,例如上面提到的touch 这个命令时,那么由这个进程衍生出来的其他

进程在一般状态下,也会沿用这个进程的相关权限

image-20240323130221602

  • 程序:通常为二进制程序,放置在存储媒介中(如硬盘)以物理文件的形式存在
  • 进程:程序被触发后,执行者的权限与属性,程序的代码与所需数据等都会被加载到内存中,操作系统给予这个内存中的单元一个标识符(PID),可以说进程就是一个正在运行中的程序

子进程与父进程

由上面说明提到【衍生出来的程序】,就是当我们登陆系统后,会获取一个bash的shell,如何我们用这个bash提供的接口去执行一个命令,例如/usr/bin/passwd或是touch等,那些另外执行的命令会被触发称为PID,这些后来执行命令所产生的PID就是【子进程】,而原本的bash环境下,就称为【父进程】

image-20230423142954077

如上图,连续执行两个bash,第二个bash的父进程就是前一个bash。每个进程都有一个PID,而某个进程的父进程可以通过Parent PID(PPID)来确定。 PPID是用来指示创造当前进程的那个进程的PID。

# 目前在bash环境下,再触发一次bash,并用ps -l查看进程相关的输出信息
[root@chenshiren ~]# bash
[root@chenshiren ~]# ps -l
F S   UID     PID    PPID  C PRI  NI ADDR SZ WCHAN  TTY          TIME CMD
0 S     0    8926    8924  0  80   0 - 56025 do_wai pts/0    00:00:00 bash
0 S     0    9054    8926  0  80   0 - 56030 do_wai pts/0    00:00:00 bash
4 R     0    9079    9054  0  80   0 - 56370 -      pts/0    00:00:00 ps
# 第一个bash的PID与第二个bash的PPID都是8926,因为第二个bash来自于第一个所产生的

fork and exec:程序调用的流程

Linux 的程序调用通常称为 fork-and-exec 的流程。进程都会借由父进程以复制(fork)的方式产生一个一模一样的子进程,然后被复制出来的子进程再以 exec 的方式来执行实际要执行的进程,最终就成为一个子进程。如下图

(1)系统先以fork的方式复制一个与父进程相同的临时进程,这个进程与父进程唯一的差别就是PID不同,PPID是父进程的PID

(2)临时进程开始以exec的方式加载实际要执行的进程,新的进程名称为qqq,最终子进程的进程代码就会变成qqq了

image-20240323134122638

系统或网络服务:常驻在内存的进程

我们执行的touch、rm、mv、chmod、chgrp、chown等命令,这些命令都是执行完就结束的,该项命令被触发后所产生的PID很快就会终止。

常驻在内存的进程通常是负责系统或网络服务的进程,它们长时间运行以提供各种功能来为用户服务。例如:计划任务(crond、atd)和负责网络连接的服务(postfix、named、apache、vsftpd)等。网络服务这些进程执行后,会启动一个可以负责网络监听的端口(port),以提供外部客户端的连接请求

任务管理

任务管理是用在bash环境下的,也就是说【当我们登陆系统获取bash shell 之后,在单一终端下同时执行多个任务的操作管理】

什么是任务管理

【 执行任务管理的操作中,其实每个任务都是目前bash的子进程,即彼此之间是有相关性的,我们无法用任务管理的方式由tty1的环境去管理tty2的bash】

Linux系统中,可以将任务分为在前台运行和在后台运行。在前台的任务与用户交互,而在后台的任务则在后台默默执行。放入后台的任务不能与用户交互,且无法使用Ctrl+C结束。举例来说,像vim这种需要用户交互的任务不能在后台中执行。

要执行bash的任务管理必须要主要到的限制:

  • 这些任务所触发的进程必须来自于你shell的子进程(只管理自己的bash)
  • 前台:可以控制与执行命令的这个环境称为前台任务
  • 后台:可以自动化执行的任务,你无法使用[ctrl+c]终止它,可以使用bg、fg调用该任务
  • 后台中【执行】的进程不能等待终端或shell的输入

job control的管理:jobs、ctrl+z、&、fg、bg、kill

直接将命令丢到后台中【执行】的&

只有一个bash的环境下,如果想要同时执行多个任务,那么可以将某些任务直接丢到后台环境当中,让我们可以继续操作前台的任务

# 示例1 要将/etc/ 整个备份称为/tmp/etc.tar.gz 且不想要等待
[root@chenshiren ~]# tar -zpcf /tmp/etc.tar.gz /etc &
[1] 9368   #  [任务编号] PID
[root@chenshiren ~]# tar: 从成员名中删除开头的“/”
# 由于我们没有加上数据量重定向,所以会影响界面,不过不会影响前台的操作
[1]+  已完成               tar -zpcf /tmp/etc.tar.gz /etc
# 可以看到任务已经完成,并且该任务的命令就是后面的那一串
# & 代表:【将任务丢到后台中去执行】,这种情况最大的好处就是不怕被ctrl + c 中断

# 示例2 如上把命令放到后台但是还是会有一些信息输出 如果你不想看到信息可以这样做
[root@chenshiren ~]# tar -zpvcf /tmp/etc.tar.gz /etc > /tmp/tar_etc.log 2>&1 &
[1] 9399  # [任务编号] PID
# 这样他输出的信息全在/tmp/tar_etc.log里面
[root@chenshiren ~]# cat /tmp/tar_etc.log 
...
...
/etc/postfix/main.cf
/etc/postfix/main.cf.proto
/etc/postfix/master.cf
/etc/postfix/master.cf.proto
/etc/postfix/postfix-files
/etc/postfix/postfix-files.d/
/etc/postfix/relocated
/etc/postfix/transport
/etc/postfix/virtual
/etc/projects
/etc/projid
[1]+  已完成               tar -zpvcf /tmp/etc.tar.gz /etc > /tmp/tar_etc.log 2>&1

将【目前】的任务丢到后台中【暂停】:[ctrl] + z

# 示例1 如果我在使用vim,却发现有个文件不知道放哪里了
# 需要到bash环境下执行查找,这时候可以暂停ctrl+z
[root@chenshiren ~]# vim ~/.bashrc 
# 按下ctrl+z
[1]+  已停止               vim ~/.bashrc
[root@chenshiren ~]#   # 跳转到了前台

查看目前的后台任务状态:jobs

[root@chenshiren ~]# jobs [-lrs]
选项:
-l  :除了列出job number与命令串之外,同时列出PID的号码
-r  :仅列出正在后台run的任务
-s  :仅列出正在后台当中暂停(stop)的任务

# 示例1 查看bash当中,所有的任务,与对应的PID
[root@chenshiren ~]# jobs -l
[1]-  9425 停止                  vim ~/.bashrc
[2]+  9432 停止                  find / -print
# 目前有两个任务在后台当中,两个任务都是暂停的,如果仅输入fg时,那么[2]会被拿到前台当中来处理
# +代表最近被放到后台的任务号码,-嗲表最近第二个被放置到后台中的任务号码
# 第三个任务以后的任务,就不会有+ -符号存在了

将后台任务拿到前台来处理:fg

[root@chenshiren ~]# fg jobnumber
选项:
jobnumber :为任务号码
# 示例1 jobs查看任务,再将任务取出
[root@chenshiren ~]# jobs -l
[1]-  9425 停止                  vim ~/.bashrc
[2]+  9432 停止                  find / -print
[root@chenshiren ~]# fg    # 如果不指定数字默认取出带+的任务
[root@chenshiren ~]# fg 1  # 取出规定的号码

让任务在后台下的状态变成运行中:bg

ctrl+z可以将任务丢到后台下面去【暂停】,那么bg就是将后台下面的任务【运行】

# 示例1 执行find / -perm /7000 > /tmp/test.txt 后,立刻丢到后台去暂停
[root@chenshiren ~]# find / -perm /7000 > /tmp/test.txt
# 按下ctrl+z 暂停丢到后台去
[2]+  已停止               find / -perm /7000 > /tmp/test.txt

# 示例2 让该任务在后台下执行
[root@chenshiren ~]# jobs ; bg 2 ; jobs
[1]-  已停止               vim ~/.bashrc
[2]+  已停止               find / -perm /7000 > /tmp/test.txt
[2]+ find / -perm /7000 > /tmp/test.txt &
[1]+  已停止               vim ~/.bashrc
[2]-  运行中               find / -perm /7000 > /tmp/test.txt &
# 由已停止变为了运行中

管理后台当中的任务:kill

kill命令用于终止正在运行的进程。当你需要停止或终止一个进程时,可以使用kill命令向该进程发送信号。通过kill命令,你可以以不同的方式影响进程,比如正常终止、强制终止等。

[root@chenshiren ~]# kill -signal jobnumber
选项:
-l  :这个是L的小写,列出目前kill能够使用的信号(signal)有哪些
signal:
  -1:重新读取一次参数的配置文件
  -2:代表由键盘输入[ctrl]+c同样的操作
  -9:立刻强制删除一个任务
  -15:以正常的进程方式终止一项任务,与-9是不一样的
  
# 示例1 找出目前bash环境下的后台任务,并将该任务【强制删除】
[root@chenshiren ~]# jobs -l
[1]+  9425 停止                  vim ~/.bashrc
[root@chenshiren ~]# kill -9 9425
[root@chenshiren ~]# jobs
[1]+  已杀死               vim ~/.bashrc
# 再过几秒执行jobs,就会发现任务1没有了,因为被删除了
# -9常用于强制删除一个不正常的任务所使用
# -15 则是以正常的步骤结束一项任务 (-15是默认值)
# 更多信号详细信息 查看 man 7 signal

脱机管理问题:nohup

在远程连接到Linux主机后,将任务使用&符号方式放到后台运行,如果在任务尚未结束的情况下断开连接(脱机),该任务会被中断,不会继续在后台执行。这是因为在远程连接断开时,终端会收到SIGHUP信号,而该信号会导致与该终端相关的后台任务被终止。为了避免任务在远程连接断开时被中断,可以使用工具如nohup任务继续在后台运行,即使连接断开

[root@chenshiren ~]# nohup [命令与参数]  # 在终端前台的任务 
[root@chenshiren ~]# nohup [命令与参数] & # 在终端后台的任务

# 示例1 编一个会【睡着500秒】的命令
[root@chenshiren ~]# vim sleep500s.sh
#!/bin/bash
# 说明:sleep 500秒 执行echo
# 时间:2024/3
/bin/sleep 500s
/bin/echo "I sleep 500s"
[root@chenshiren ~]# chmod a+x sleep500s.sh 
[root@chenshiren ~]# nohup ./sleep500s.sh &
[1] 9532
[root@chenshiren ~]# nohup: 忽略输入并把输出追加到'nohup.out'  # 会把输出重定向到~/nohup.out
[root@chenshiren ~]# exit
# 再次进入使用pstree查看进程,会发现sleep500s.sh还在执行,并不会中断

进程管理

查看进程:ps、top、pstree

可以使用静态的ps或是动态的top命令,还可以利用pstree查看进程树之间的关系

ps:将某个时间点的进程运行情况取下来

[root@chenshiren ~]# ps aux  # 查看系统所有的进程
[root@chenshiren ~]# ps -lA  # 也是能够查看所有系统的进程
[root@chenshiren ~]# ps axjf # 连同部分进程树状态
选项:
-A:所有的进程均显示出来,与-e具有同样的效果
-a:不显示与终端有关的所有进程
-u:有效使用者相关的进程
x:列出较完整信息
输出格式规划:
l :较长,较详细的将该PID的信息列出
j :任务的格式
-f:做一个更为完整的输出

仅查看自己的bash相关进程:ps -l

# 示例1 将目前属于自己这次登陆的PID与相关信息列出来(只与自己的bash有关)
[root@chenshiren ~]# ps -l
F S   UID     PID    PPID  C PRI  NI ADDR SZ WCHAN  TTY          TIME CMD
0 S     0    9553    9551  0  80   0 - 56058 do_wai pts/0    00:00:00 bash
4 R     0    9625    9553  0  80   0 - 56370 -      pts/0    00:00:00 ps
  • F:代表这个进程标识,说明这个进程的权限,常见号码由:
    • 若为4表示此进程的权限为root
    • 若为1表示此子进程仅执行复制(fork)而没有实际执行(exec)
  • S:代表这个进程的状态(STAT),主要状态有:
    • R(running):该进程正在运行中
    • S(sleep):该进程目前正在睡眠状态,但可以被唤醒
    • D:不可被唤醒的睡眠状态,通常这个进程可能在等待I/O的情况
    • T:停止状态(stop),可能是在任务控制(后台暂停)或跟踪(traced)的状态
    • Z(Zombie):僵尸状态,进程已经终止但是却无法被删除至内存外
  • UID/PID/PPID:代表【此进程被UID所拥有/进程的PID号码/此进程的父进程PID号码】
  • C:代表CPU使用率,单位为百分比
  • PRI/NI:Priority/NIce的缩写,代表此进程被CPU所指向的优先级,数值越小代表该进程越快被CPU执行
  • ADDR/SZ/WCHAN:ADDR指出进程在内存那个部分,如果是running的进程显示【-】,SZ表示用掉多少内存;WCHAN表示目前进程是否在运行,【-】表示在运行
  • TTY:登陆者的终端位置,若为远程登陆则使用动态终端接口名称(pts/n)
  • TIME:使用的 CPU 时间,注意,是此进程实际花费 CPU 运行的时间,而不是系统时间
  • CMD:就是 command 的缩写,表示造成此进程的触发进程的命令是什么

查看系统所有进程:ps aux

# 示例2 列出目前所有的正在内存当中的进程
[root@chenshiren ~]# ps aux
USER         PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root           1  0.0  0.1 170936 14904 ?        Ss   3月22   0:02 /usr/lib/systemd/systemd rhgb --switched-root --system --deserialize 31
root           2  0.0  0.0      0     0 ?        S    3月22   0:00 [kthreadd]
root           3  0.0  0.0      0     0 ?        I<   3月22   0:00 [rcu_gp]
root           4  0.0  0.0      0     0 ?        I<   3月22   0:00 [rcu_par_gp]
....
root        9553  0.0  0.0 224232  5928 pts/0    Ss   16:13   0:00 -bash
....
....
  • USER:该进程属于所属用户账号
  • PID:该进程的进程ID
  • %CPU:该进程使用掉的CPU资源百分比
  • %MEM:该进程所占用的物理内存百分比
  • VSZ:该进程使用掉的虚拟内存量(KB)
  • RSS:该进程占用的固定的内存量(KB)
  • TTY:该进程是在哪个终端上面运行,ty1-tty6是本机上面的登录进程,若为 pts/0等,则表示是由网络连接进入主机的进程
  • STAT:该进程目前的状态,状态显示与ps-l的S标识相同(R/S/T/Z)
  • TIME:该进程实际使用 CPU 运行的时间
  • COMMAND:该进程的实际命令是什么

如果发现CMD后面接上了就代表该进程是僵尸进程

# 示例3 以示例1的显示内容,显示出所有的进程
[root@chenshiren ~]# ps -Al
F S   UID     PID    PPID  C PRI  NI ADDR SZ WCHAN  TTY          TIME CMD
4 S     0       1       0  0  80   0 - 42734 ep_pol ?        00:00:02 systemd
1 S     0       2       0  0  80   0 -     0 kthrea ?        00:00:00 kthreadd
1 I     0       3       2  0  60 -20 -     0 rescue ?        00:00:00 rcu_gp
1 I     0       4       2  0  60 -20 -     0 rescue ?        00:00:00 rcu_par_gp
...
...
# 可以看到和示例1输出的情况相同

# 示例4 列出类似进程树的进程显示
[root@chenshiren ~]# ps axjf
   PPID     PID    PGID     SID TTY        TPGID STAT   UID   TIME COMMAND
      0       2       0       0 ?             -1 S        0   0:00 [kthreadd]
      2       3       0       0 ?             -1 I<       0   0:00  \_ [rcu_gp]
      2       4       0       0 ?             -1 I<       0   0:00  \_ [rcu_par_gp]
...
      1    1091    1091    1091 ?             -1 Ss       0   0:00 sshd: /usr/sbin/sshd -D [listener] 0 of 10-100 startups
   1091    9548    9548    9548 ?             -1 Ss       0   0:00  \_ sshd: root [priv]
   9548    9551    9548    9548 ?             -1 S        0   0:00      \_ sshd: root@pts/0
   9551    9553    9553    9553 pts/0       9670 Ss       0   0:00          \_ -bash
   9553    9670    9670    9553 pts/0       9670 R+       0   0:00              \_ ps axjf
...

# 示例5 找出cron 与 rsyslog这两个服务有关的PID号码
[root@chenshiren ~]# ps aux |grep -E '(cron|rsyslog)'
root         913  0.0  0.0 164064  7416 ?        Ssl  3月22   0:01 /usr/sbin/rsyslogd -n
root        1177  0.0  0.0 223948  3864 ?        Ss   3月22   0:00 /usr/sbin/crond -n
root        9682  0.0  0.0 221812  2484 pts/0    S+   17:36   0:00 grep --color=auto -E (cron|rsyslog)

top:动态查看进程的变化

[root@chenshiren ~]# top [-d] top [-bnp]
选项:
-d:后面可以接秒数,就是整个进程界面更新的秒数,默认是5秒
-b:以批量的方式执行top
-n:与-b搭配,需要执行几次top的输出结果
-p:指定某些个PID来执行查看监测而已

在top执行过程中可以使用的按键

按键作用
?显示在 top 当中可以输入的按键命令
P以CPU的使用排序显示
M以Memory 的使用排序显示
N以 PID 来排序
T由该进程使用的CPU 时间累积(TIME+)排序
k给予某个 PID 一个信号(signal)
r给予某个 PID 重新制订一个 nice 值
q退出top的按键

top输出

image-20240323183311889

  • 第一行(top…)这一行显示的信息分别为:
    • 目前的时间:18:32:58
    • 开机到目前为止所经过的时间 19:20
    • 已经登陆系统的用户人数,1user
    • 系统在1、5、15分钟的平均任务负载,若高于1表示系统进程太过频繁了
  • 第二行(Tasks…):显示的是目前进程的总量与个别进程在什么状态(running、sleeping、stopped、zombie )
  • 第三行(%Cpus…):CPU使用率统计信息,(us)包括用户空间占用、(sy)内核空间占用、(ni)nice值占用、(id)空闲时间、(wa)等待IO时间、(hi)硬中断时间、(si)软中断时间、(st)虚拟化占用时间
  • 第四行(MiB Mem…):内存使用统计信息,包括总内存大小、空闲内存大小、已用内存大小、缓存和缓冲区内存大小
  • 第五行(MiB Swap…):交换空间使用统计信息,包括总交换空间大小、空闲交换空间大小、已用交换空间大小、可用内存大小

top下半部分

  • PID:每个进程的ID
  • USER:该进程所属的用户
  • PR:Priority的简写,进程的优先执行顺序,越小则越早被执行
  • NI:nice的简写,与Priority有关,也是越小则越早被执行
  • %CPU:CPU的使用率
  • %MEM:内存的使用率
  • TIME+:CPU使用时间的累加
# 示例1 将top的信息执行2此,然后将结果输出到/tmp/top.txt
[root@chenshiren ~]# top -b -n 2 > /tmp/top.txt

# 示例2 我们自己的bash PID可由$$变量获取,使用top持续查看该PID
[root@chenshiren ~]# echo $$         
9553
[root@chenshiren ~]# top -d 2 -p 9553
...
...
    PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND                                                                                         
   9553 root      20   0  224232   6024   3928 S   0.0   0.1   0:00.07 bash     

pstree

pstree 命令用于以树状结构显示进程之间的父子关系,展示系统中运行的进程的层次结构

[root@chenshiren ~]# pstree [-A|U] [-up]
选项:
-A :各进程树之间的连接以ASCII字符来连接
-U :各进程树之间的连接以Unicode的字符来连接,在某些终端界面下可能会有错误
-p :并同时列出每个进程的PID
-u :并同时列出每个进程的所属账户名称

# 示例1 列出目前系统上面所有的进程树的相关性
[root@chenshiren ~]# pstree -A
systemd-+-ModemManager---2*[{ModemManager}]   # 这行是ModenManger与其子进程
        |-NetworkManager---2*[{NetworkManager}] # 前面的数字代表子进程数量
        ...
        ...
        |-sshd---sshd---sshd---bash---pstree  # 命令的依赖性
        ...
        
# 示例2 承上,同时显示PID与users
[root@chenshiren ~]# pstree -Aup
systemd(1)-+-ModemManager(988)-+-{ModemManager}(1026)
           |                   `-{ModemManager}(1036)
           |-NetworkManager(1082)-+-{NetworkManager}(1085)
           .....
           |-sshd(1091)---sshd(9548)---sshd(9551)---bash(9553)---pstree(9975)
           .....
           # ()内的就是PID还有owner

进程的管理:kill

进程之间可以通过信号进行控制和通信。信号是一种用来告知进程需要采取某种操作的机制。在Linux系统中,可以使用kill -lman 7 signal命令来查看可用信号的列表。通过发送适当的信号,可以控制进程的行为,比如关闭、重新启动等。

主要信号的代号名称内容如下:

代号名称内容
1SIGHUP启动被终止的进程,可让该 PID 重新读取自己的配置文件,类似重新启动
2SIGINT相当于用键盘输入[ctrl]+c来中断一个进程的运行
9SIGKILL代表强制中断一个进程的执行,如果该进程执行到一半,那么尚未完成的部分可能会有【半成品】产生,类似 vim 会有 .filename.swp 保留下来
15SIGTERM以正常的方式结束进程来终止该进程。由于是正常的终止,所以后续的操作会将它完成。不过,如果该进程已经发生问题,就是无法使用正常的方法终止时输入这个信号也是没有用的
19SIGSTOP相当于用键盘输入[ctrl]-z 来暂停一个进程的运行

kill -signal PID

kill可以帮我们将这个信号传送给某个任务(%jobnumber)或是某个PID(直接输入数字)。

要再次强调的是:kill后面直接加数字与加上 %number 的情况是不同的

例题:

以ps找出rsyslogd这个进程的PID,再使用kill传递传送信息,使得rsyslogd可以重新读取配置文件

# 由于需要重新读取配置文件,因此signal是1号。找出rsyslogd的PID
[root@chenshiren ~]# ps aux |grep 'rsyslogd' |grep -v 'grep'|awk '{print $2}'
913
# 接下来则是实际使用kill -1 PID
[root@chenshiren ~]# kill -1 $(ps aux |grep 'rsyslogd' |grep -v 'grep'|awk '{print $2}')

killall -signal命令名称

killall命令用于根据进程名称管理进程

[root@chenshiren ~]# killall [-iIe] [command name]
选项:
-i :interactive及互动的意思,若需要删除,会出现提示字符给使用者
-e :exact的意思,表示【后面接的command name 要一致】但整个完整的命令不能超过15个字符
-I :命令名称(可能含参数)忽略大小写

# 示例1 给予rsyslogd这个命令启动的PID一个SIGHUP的信号
[root@chenshiren ~]# killall -1 rsyslogd  

# 示例2 强制终止所有以httpd启动的进程
[root@chenshiren ~]# killall -9 httpd

# 依次询问每个bash进程是否需要被终止
[root@chenshiren ~]# killall -i -9 bash
信号 bash(9553) ? (y/N) 

关于进程的执行顺序:nice、renice

进程分配优先级是非常重要的,以确保紧急任务能够及时得到处理。在Linux中,进程会被赋予不同的优先级,使重要或紧急任务能够得到更多的CPU时间,而不至于被排在队列的末尾。 通过设置不同的进程优先级,可以确保紧急任务得到及时处理,而不会被长时间阻塞在队列中

为了实现优先级的功能,Linux给予进程一个所谓的【PRI】这个PRI值越低代表越优先的意思。不过这个PRI值是由内核动态调整的,用户无法之间调整PRI值

[root@chenshiren ~]# ps -l
F S   UID     PID    PPID  C PRI  NI ADDR SZ WCHAN  TTY          TIME CMD
0 S     0    9553    9551  0  80   0 - 56192 do_wai pts/0    00:00:00 bash
4 R     0   10126    9553  0  80   0 - 56370 -      pts/0    00:00:00 ps
# PRI是内核动态调整的,如果要调整进程的优先级,就要通过nice值了,nice值就是上表的NI
PRI(new) = PRI(old) + nice
# nice值可调整范围 -20 ~ 19
# root可随意调整自己或它人进程的nice值,且范围为 -20 ~ 19
# 一般用户仅可调整自己的进程的nice值,且范围仅为 0 ~ 19(避免一般用户抢占资源)
# 一般用户仅可将nice值越调越高,例如本来nice为5,则未来仅能调整大于5

nice:新执行的命令即给予新的nice值

[root@chenshiren ~]# nice [-n 数字] command
选项:
-n :后面接一个数字,数值的范围-20 ~ 19

# 示例1 用root给一个nice值为-5,用于执行vim,并查看该进程
[root@chenshiren ~]# nice -n -5 vim &
[1] 10132
[root@chenshiren ~]# ps -l
F S   UID     PID    PPID  C PRI  NI ADDR SZ WCHAN  TTY          TIME CMD
0 S     0    9553    9551  0  80   0 - 56192 do_wai pts/0    00:00:00 bash
4 T     0   10132    9553  0  75  -5 - 57432 do_sig pts/0    00:00:00 vim
4 R     0   10133    9553  0  80   0 - 56370 -      pts/0    00:00:00 ps
# PRI与NI各减5
[root@chenshiren ~]# kill -9 10132

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

[root@chenshiren ~]# renice [number] PID
选项:
PID : 某个进程的ID

# 示例1 找出自己的bash PID 并将PIDnice调整到 -5
[root@chenshiren ~]# ps -l
F S   UID     PID    PPID  C PRI  NI ADDR SZ WCHAN  TTY          TIME CMD
0 S     0    9553    9551  0  80   0 - 56353 do_wai pts/0    00:00:00 bash
4 R     0   10139    9553  0  80   0 - 56370 -      pts/0    00:00:00 ps
[root@chenshiren ~]# renice -5 9553
9553 (process ID) 旧优先级为 0,新优先级为 -5
[root@chenshiren ~]# ps -l         
F S   UID     PID    PPID  C PRI  NI ADDR SZ WCHAN  TTY          TIME CMD
0 S     0    9553    9551  0  75  -5 - 56353 do_wai pts/0    00:00:00 bash
4 R     0   10141    9553  0  75  -5 - 56370 -      pts/0    00:00:00 ps

查看系统资源信息:free、uname、uptime、netstat、dmesg、vmstat

free:查看内存使用情况

[root@chenshiren ~]# free [-b|-k|-mg|-g|-h] [-t] [-s N -c N]
选项:
-b: 直接输入free时,显示的单位是KBytes,可以使用 b(Bytes)、m(MBytes)、k(KBytes)、g(GBytes)
     -h 让系统自己指定单位
-t:在输出的最终结果,显示物理内存与swap的总量
-s:可以让系统不断刷新显示数据,后面接秒,几秒刷新一次
-c:让free打印几次

# 示例1 显示目前系统的内存容量
[root@chenshiren ~]# free -h
               total        used        free      shared  buff/cache   available
Mem:           7.7Gi       1.1Gi       5.9Gi        15Mi       1.0Gi       6.6Gi
Swap:          5.0Gi          0B       5.0Gi

uname:查看系统与内核相关信息

[root@chenshiren ~]# uname [-asrmpi]
选项:
-a :所有系统相关的信息,包括下面的数据都会被列出来
-s :系统内核名称
-r :内核的版本
-m :系统的硬件架构
-p :CPU的类型,与-m相似
-i :硬件的平台

# 示例1 输出系统的基本信息
[root@chenshiren ~]# uname -a
Linux chenshiren 5.14.0-284.11.1.el9_2.x86_64 #1 SMP PREEMPT_DYNAMIC Wed Apr 12 10:45:03 EDT 2023 x86_64 x86_64 x86_64 GNU/Linux

uptime:查看系统启动时间与任务负载

[root@chenshiren ~]# uptime
 22:07:31 up 22:55,  1 user,  load average: 0.00, 0.00, 0.04

netstat:追踪网络或socket文件

netstat命令用于显示网络状态信息,包括网络连接、路由表、接口统计信息等

netstat -[rn]      # 与路由有关的参数
netstat -[antulpc] # 与网络接口有关的参数
选项:
-r:列出路由表(route table),功能如同 route这个命令
-n:不使用主机名与服务名称,使用IP与port number,如同route -n 与网络接口有关的参数
-a:列出所有的连接状态,包括 tcp/ydp/unix socket 等
-t:仅列出TCP数据包的连接
-u:仅列出UDP数据包的连接
-l:仅列出已在Listen(监听)的服务的网络状态
-p:列出PID与Program的文件名
-c:可以设置几秒钟自动更新一次,例如 -c 5 为每5s更新一次网络状态的显示

# 示例1  列出当前的所有网络连接状态,使用IP与port number
[root@chenshiren ~]# netstat -an 
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State      
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN     
tcp        0      0 127.0.0.1:631           0.0.0.0:*               LISTEN
tcp        0      0 127.0.0.1:25            0.0.0.0:*               LISTEN
...
...
Active UNIX domain sockets (servers and established)
Proto RefCnt Flags       Type       State         I-Node   Path
unix  2      [ ACC ]     STREAM     LISTENING     26134    @/tmp/dbus-R39MpMK6
unix  2      [ ACC ]     STREAM     LISTENING     27802    @/tmp/.ICE-unix/1218
...
...

网络连接情况部分:

  • Proto:网络的封包协议,主要分为TCP与UDP封包

  • Recv-Q:由非用户程序连接所复制而来的总 bytes 数

  • Send-Q:由远程主机发送而来,但不具有ACK标志的总bytes数,亦指主动连接SYN或其他标志的数据包所占的 bytes 数

  • Local Address:本地端的IP:port情况

  • Foreign Address:远程主机的IP:port情况

  • State:连接的状态,常见的状态有:

    LISTEN(正在监听)

    ESTABLISHED(已建立连接)

    SYN_SENT:发出注定连接(SYN标志)的连接数据包

    SYN_RECV:接受到一个要求连接的主动连接数据包

    FIN_WAIT1:该套接字服务(socket)已中断,该连接正在断线当中

    FIN_WAIT2:该连接已挂断,但正在等待对方主机响应断线确认的数据包

    TIME_WAIT:该连接已挂断,但socket还在网络上等待结束

socket文件的输出字段部分:

  • Proto:一般就是unix
  • RefCnt:连接到此socket的进程数量
  • Flags:连接的标识
  • Type:socket存取的类型。有确认连接的STREAM与不需确认的DGRAM两种
  • State:若为CONNECTED则表示多个进程之间已经建立连接
  • Path:连接到此socket的相关进程的路径,或是相关数据输出的路径
# 示例2 找出目前系统上已在监听的网络连接及PID

image-20240323223031846

dmesg:分析内核产生的信息

dmesg命令用于显示系统在启动过程中由内核产生的信息,也可以用于实时显示内核的消息缓冲区内容。

# 示例1 输出内核启动的信息
[root@chenshiren ~]# dmesg | more
# 示例2 查找启动的时候,硬盘的相关信息
[root@chenshiren ~]# dmesg | grep nvme
[    1.952134] nvme nvme0: pci function 0000:0b:00.0
[    1.955662] nvme nvme0: 15/0/0 default/read/poll queues
[    1.966144]  nvme0n1: p1 p2 p3
[    1.981090]  nvme0n2: p1 p2 p3 p4
[    4.604035] XFS (nvme0n1p2): Mounting V5 Filesystem
[    4.612603] XFS (nvme0n1p2): Starting recovery (logdev: internal)
[    4.614432] XFS (nvme0n1p2): Ending recovery (logdev: internal)
...
...

vmstat:检测系统资源变化

vmstat命令用于显示虚拟内存统计信息,可以检测系统资源的变化并实时监控系统的性能。

[root@chenshiren ~]# vmstat [-a] [延迟 [总计检测次数]]  # CPU内存等信息
[root@chenshiren ~]# vmstat [-fs]     # 内存相关
[root@chenshiren ~]# vmstat [-S 单位]  # 设置显示数据的单位
[root@chenshiren ~]# vmstat [-d]      # 与磁盘有关
[root@chenshiren ~]# vmstat [-p 分区] # 与磁盘有关
选项:
-s :使用 inactive/active(活动与否)替换buffer/cache的内存输出信息
-f :开机到目前为止,系统复制(fork)的进程数.
-s :将一些事件(启动至目前为止)导致的内存变化情沉列表说明
-S :后面可以接单位,让显示的数据有单位,例如K/替换Bytes的容量
-d :列出磁盘的读写总量统计表
-p :后面列出分区,可显示该分区的读写总量统计表

# 示例1 统计目前主机CPU状态,每秒一次,共计三次
[root@chenshiren ~]# vmstat 1 3
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 0  0      0 6199460   6724 1029816    0    0     5     7   29   42  0  0 100  0  0
 0  0      0 6199460   6724 1029856    0    0     0     0  119  163  0  0 100  0  0
 0  0      0 6199460   6724 1029856    0    0     0     0  113  152  0  0 100  0  0

字段意义:

  • 进程字段

    r:等待运行中的进程数量

    b:不可被唤醒的进程数量

  • 内存字段

    swpd:虚拟内存被使用的容量

    free:未被使用的内存容量

    buff:用于缓存存储器

    cache:用于高速缓存

  • 内存交换分区(swap)

    si:有磁盘中将进程取出的容量

    so:由于内存不足而将没用到的进程写入到磁盘的swap的容量

  • 磁盘读写(I/O)

    bi:由磁盘读入的区块数量

    bo:写入到磁盘中的区块数量

  • 系统

    in:每秒被中断的进程次数

    cs:每秒执行的事件切换次数

  • CPU

    us:非内核层的 CPU 使用状态

    sy:内核层所使用的 CPU 状态

    id:闲置的状态

    wa:等待 I/0 所耗费的 CPU 状态

    st:被虚拟机(virtual machine)所使用的 CPU 状态

# 系统上面所有的磁盘的读写状态
[root@chenshiren ~]# vmstat -d
disk- ------------reads------------ ------------writes----------- -----IO------
       total merged sectors      ms  total merged sectors      ms    cur    sec
nvme0n1  20141   1290 1609276    4322   9711   2976  643487    4294      0     10
nvme0n2  84517  52353 10241427   57443  19498 126957 4520851    6080      0      3
sr0      777      0   26492      98      0      0       0       0      0      0
dm-0   19239      0 1486425    4837  12474      0  639120    5495      0      9
dm-1      99      0    4696       8      0      0       0       0      0      0
md0      489      0   13323      31    175      0   25830     243      0      0

特殊文件与进程

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

SUID的程序如何被一般用户执行,具有上面特点

  • SUID权限仅对二进制程序有效
  • 执行者戳该程序需要具有x的可执行权限
  • 本权限对于执行该程序的过程中有效
  • 执行者将具有该程序拥有者(owner)的权限

当一个拥有SUID权限的程序被触发执行时,一个新的进程会被创建,该进程会继承该程序的SUID权限,从而使执行者具有程序拥有者的特殊权限。这种机制使得普通用户在执行某些需要特殊权限的程序时可以暂时获得特权,例如执行passwd命令更改密码

[root@chenshiren ~]# su - csq           
[csq@chenshiren ~]$ passwd
更改用户 csq 的密码 。
当前的密码:    # 这里按下 ctrl + z 并按下Enter

[1]+  已停止               passwd

[csq@chenshiren ~]$ pstree -uA
....
...
|-sshd---sshd---sshd---bash---su---bash(csq)-+-passwd(root)  
|                                            `-pstree
...
...
# 可以看到passwd 确实是由csq用户的bash衍生出阿里的,不过权限不一样

/proc/*代表的意义

/proc 目录是一个特殊的虚拟文件系统,它不包含真正的文件,而是包含当前运行中的进程和内核信息的虚拟文件系统

[root@chenshiren ~]# ll /proc
总用量 0
dr-xr-xr-x  9 root           root                         0  322 11:43 1
...
...
dr-xr-xr-x  9 root           root                         0  322 11:43 990
....
-r--------  1 root           root                         0  323 15:48 timer_list
dr-xr-xr-x  6 root           root                         0  323 13:24 tty
-r--r--r--  1 root           root                         0  322 11:43 uptime
-r--r--r--  1 root           root                         0  323 15:48 version
-r--------  1 root           root                         0  323 15:48 vmallocinfo
-r--r--r--  1 root           root                         0  322 11:43 vmstat
-r--r--r--  1 root           root                         0  322 11:43 zoneinfo

基本上,目前主机上面的各个进程的PID都以目录的形式存在于/proc当中。

例如,我们启动所执行的第一个程序systemd的PID是1,这个PID的所有相关信息都写入/proc/1/*当中。

root@chenshiren ~]# ll /proc/1/
总用量 0
-r--r--r--  1 root root 0  323 15:26 arch_status
dr-xr-xr-x  2 root root 0  322 11:43 attr
-rw-r--r--  1 root root 0  323 15:26 autogroup
-r--------  1 root root 0  323 15:26 auxv
-r--r--r--  1 root root 0  322 11:43 cgroup
--w-------  1 root root 0  323 15:26 clear_refs
-r--r--r--  1 root root 0  322 11:43 cmdline
-rw-r--r--  1 root root 0  322 11:43 comm   # 命令串
-rw-r--r--  1 root root 0  322 19:11 coredump_filter
-r--r--r--  1 root root 0  323 15:26 cpu_resctrl_groups
-r--r--r--  1 root root 0  323 15:26 cpuset
-r--------  1 root root 0  322 11:43 environ # 一些环境变量
...
...
  • cmdline:这个进程被启动的命令串
  • environ:这个进程的环境变量内容
文件名文件内容
/proc/cmdline加载内核时所执行的相关命令与参数,查看此文件,可了解命令是如何启动的
/proc/cpuinfo本机的 CPU 的相关信息,包含频率、类型与功能等
/proc/devices这个文件记录了系统各个主要设备的主要设备代号,于mknod有关
/proc/filesystems目前系统已经加载的文件系统
/proc/interrupts目前系统上面的 IRQ 分配状态
/proc/ioports目前系统上面各个设备所配置的 I/O 地址
/proc/kcore这个就是内存的大小,不要读它
/proc/loadavg记录了系统的负载情况,包括1分钟、5分钟、15分钟的平均负载
/proc/meminfo使用 free 列出的内存信息,在这里也能够查看到
/proc/modules目前我们的 Linux 已经加载的模块列表,也可以想成是驱动程序
/proc/mounts系统已经挂载的数据,就是用 mount 这个命令调用出来的数据
/proc/swaps显示系统当前正在使用的 swap 分区(交换分区)的详细信息
/proc/partitions录了系统中所有磁盘分区的信息,相当于fdisk -l的输出。
/proc/uptime就是用 uptime 的时候,会出现的信息
/proc/version内核的版本,就是用 uname -a 显示的内容
/proc/bus/*一些总线的设备,还有 USB 的设备也记录在此

查询已使用文件或已执行进程使用的文件:fuser、lsof、pidof

fuser:借由文件(或文件系统)找出正在使用该文件的进程

fuser命令是在Linux系统中用于查找进程使用的文件的工具

例如:如果在卸载时发现系统通知【device is busy】,则表示此文件系统正在忙碌中,表示有某个进程正在使用该文件系统

[root@chenshiren ~]# fuser [-umv] [-k [i] [-signal]] file/dir
选项:
-u:除了进程的 PID 之外,同时列出该进程的拥有者
-m:后面接的那个文件名会主动地上提到该文件系统的最顶层,对umount不成功很有效
-v:可以列出每个文件与进程还有命令的完整相关性
-k:找出使用该文件/日录的 PID,并试图以SIGKILL 这个信号给予该 PID
-i:必须与-k 配合,在删除 PID 之前会先询问使用者意愿
-signal:例如-1、-15等,若不加的话,默认是 SIGKILL(-9)

# 示例1 找出目前所在目录的使用 PID/所属账号/权限是什么

[root@chenshiren ~]# fuser -uv .
                     用户     进程号 权限   命令
/root:               root       9553 ..c.. (root)bash

权限部分:
# c :此进程在当前的目录下
# e :可被触发为执行状态
# f :是一个被开启的文件
# r :代表顶层目录
# F :该文件被使用了,不过在等待响应中
# m :可能为共享的动态函数库

# 示例2 找到所有使用到/proc这个文件系统的进程
[root@chenshiren ~]# fuser -uv /proc
                     用户     进程号 权限   命令
/proc:               root     kernel mount (root)/proc
                     rtkit       915 .rc.. (rtkit)rtkit-daemon

# 示例3 查看/proc目录下有多少进程正在占用该文件系统
[root@chenshiren ~]# fuser -muv /proc
                     用户     进程号 权限   命令
/proc:               root     kernel mount (root)/proc
                     root          1 f.... (root)systemd
                     root        756 f.... (root)systemd-journal
                     rtkit       915 .rc.. (rtkit)rtkit-daemon
                     root        920 f.... (root)udisksd
                     gdm        1196 f.... (gdm)systemd
                     gdm        1228 f.... (gdm)gnome-shell
                     root       1344 f.... (root)packagekitd
                     gdm        1425 f.... (gdm)gsd-housekeepin
                     root       6457 f.... (root)mdadm
                     root       8896 f.... (root)systemd
                     

针对单一文件

# 示例4 找到/run下面属于FIFO类型的文件,并且找出读取该文件的进程
[root@chenshiren ~]# find /run -type p
/run/initctl
...
...
/run/systemd/sessions/c1.ref
/run/systemd/inaccessible/fifo
[root@chenshiren ~]# fuser -uv /run/systemd/sessions/c1.ref 
                     用户     进程号 权限   命令
/run/systemd/sessions/c1.ref:
                     root        919 f.... (root)systemd-logind
                     root       1190 F.... (root)gdm-session-wor

lsof:列出被进程所使用的文件名称

[root@chenshiren ~]# lsof [-aUu] [+d]
选项:
-a:多项数据需要【同时成立】才显示处结果时
-U:仅列出UNIX-like系统的socket文件类型
-u:后面接username,列出该使用者相关进程所使用的文件
+d:后面接目录,找出某个目录下面已经被使用的文件

# 示例1 列出目前系统上面所有已经被开启的文件与设备
[root@chenshiren ~]# lsof
COMMAND     PID  TID TASKCMD     USER   FD      TYPE      DEVICE  SIZE/OFF   NODE NAME
systemd       1                   root   cwd     DIR       53,0     268       128  /
systemd       1                  root    rtd    DIR       253,0     268       128 /
...
...
# 默认情况下,lsof会将目前系统上面已经打开的文件全部列出来

# 示例2 仅列出关于root的所有进程所使用的socket文件
[root@chenshiren ~]# lsof -u root -a -U
[root@chenshiren ~]# lsof -u root -a -U
COMMAND    PID USER   FD   TYPE             DEVICE SIZE/OFF   NODE NAME
systemd      1 root   16u  unix 0xffff918f9236bfc0      0t0  17032 /run/systemd/private type=STREAM (LISTEN)
systemd      1 root   25u  unix 0xffff918f82e8f2c0      0t0  17128 type=DGRAM (CONNECTED)
systemd      1 root   44u  unix 0xffff918f9267a200      0t0  15679 /run/systemd/io.system.ManagedOOM type=STREAM (LISTEN)
systemd      1 root   45u  unix 0xffff918f9267ea40      0t0  15678 /run/systemd/userdb/io.systemd.DynamicUser type=STREAM (LISTEN)
systemd      1 root   60u  unix 0xffff918f92369540      0t0  17362 type=STREAM (CONNECTED)
systemd      1 root   77u  unix 0xffff918f92677b40      0t0  15673 /run/systemd/notify type=DGRAM (CONNECTED)
systemd      1 root   87u  unix 0xffff918f92673740      0t0  15674 type=DGRAM (CONNECTED)
...
...

# 示例3 列出目前系统上所有的被使用的外接设备
[root@chenshiren ~]# lsof +d /dev/
COMMAND    PID           USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
systemd      1           root    0u   CHR    1,3      0t0    4 /dev/null
systemd      1           root    1u   CHR    1,3      0t0    4 /dev/null
systemd      1           root    2u   CHR    1,3      0t0    4 /dev/null
systemd      1           root    3w   CHR   1,11      0t0   10 /dev/kmsg
systemd      1           root   27r   CHR 10,235      0t0   98 /dev/autofs
systemd      1           root  142u   CHR 10,242      0t0  149 /dev/rfkill
...
...

# 示例4 显示属于root的bash这个程序所开启的文件
[root@chenshiren ~]# lsof -u root | grep bash
bash       9553 root  cwd       DIR              253,0      4096   33554562 /root
bash       9553 root  rtd       DIR              253,0       268        128 /
bash       9553 root  txt       REG              253,0   1388904   33667025 /usr/bin/bash
bash       9553 root  mem       REG              253,0 223542144   33644564 /usr/lib/locale/locale-archive
bash       9553 root  mem       REG              253,0    148429   33667060 /usr/share/locale/zh_CN/LC_MESSAGES/bash.mo
bash       9553 root  mem       REG              253,0   2387240   67314221 /usr/lib64/libc.so.6
bash       9553 root  mem       REG              253,0    129294   33644563 /usr/share/locale/zh_CN/LC_MESSAGES/libc.mo
bash       9553 root  mem       REG              253,0    191600   67314145 /usr/lib64/libtinfo.so.6.2
...
...

pidof:找出某个正在执行的进程的PID

[root@chenshiren ~]# pidof [-sx] 程序名
选项:
-s:仅列出一个PID而不列出所有的PID
-x:同时列出该程序名可能的PPID那个进程的PID

# 示例1 列出目前系统上面systemd以及rsyslogd这两个程序的PID
[root@chenshiren ~]# pidof systemd rsyslogd
[root@chenshiren ~]# pidof systemd
8898 8896 1197 1196 1
[root@chenshiren ~]# pidof systemd rsyslogd
8898 8896 1197 1196 1 913
  • 28
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值