Linux基础学习笔记-进程管理

前言

以下是关于Linux进程管理的重要内容。

Linux进程管理

什么是进程

Linux下面所有的命令和能够执行的操作都和权限相关,系统如何判断你的权限?当然是UID和GID。在Linux系统里:触发任意一个事件的时候,系统都会将它定义成一个进程,并且给予这个进程一个ID,称为PID,同时根据触发这个进程的用户与相关属性关系,给予这个PID一组有效的权限设置。以后这个PID能做的事情就与这个PID有关的权限有关系。

进程与程序

如何产生一个进程:执行一个程序或者命令即可获取一个PID。系统只认识二进制文件,我们要让系统工作的时候,就需要启动二进制文件,这个二进制文件就是程序。

每个进程都有三组权限,每组都有rwx的权限,所以不同用户身份执行这个程序时,系统给予的权限也都不一样。程序一般是放置在物理磁盘中的,通过用户来触发,触发后会加载到内存里成为一个个体,为进程。为了让操作系统可以管理这个进程,进程会给予执行者权限等参数,以及进程所需要的脚本数据等,最后再给一个PID。操作系统根据PID来判断进程是否具有执行权限。

M8xH4f.png

  • 程序:通常是二进制文件以物理文件的方式存储
  • 进程:正在运行中的程序

子进程和父进程

当一个进程执行作业时,由这个进程衍生出来的其他进程在一般状态下,也会沿用这个进程的相关权限。在登录系统以后,用户会获取一个bash的shell,我们用这个bash提供的接口去执行另一个命令,例如touch,这些另外执行的命令也会被触发为PID,后来产生的PID就是子进程,而原来的bash环境就被称为父进程,通过PPID来判断

MYLSFf.png

fork和exec

linux的程序调用通常称为fork-and-exec的流程。进程都会借父进程以fork的方式产生一个一毛一样的子进程,然后被复制出来的子进程再以exec的方式来执行需要执行的进程,最终就成为一个子进程

MYX7WT.png

任务管理

任务管理是用在bash环境下:当我们登录系统获得shell之后,在单一终端下同时执行多个任务的操作管理

什么是任务管理

执行任务管理的过程中,每个任务都是目前bash的子进程,彼此间之间是有相关性的,我们无法用任务管理的方式从tty1的环境去管理tty2的bash;

假设我们只有一个终端,因此:可以出现提示字符,让你操作的环境就成为前台,其他任务就可以放入后台去暂停或者运行;需要注意的是放入后台的任务想要运行的时候,绝对不可以和用户产生交互,无法被[ctrl]+[c]终止。

job control的管理

bash只能管理自己的任务而不能管理其他bash的任务,所以即使是root也不能将别的bash下面的job拿来执行,实际上执行job控制的命令如下:

&

输入一个命令后,在该命令后直接加上一个&,表示的是直接将命令丢到后台去执行,bash会给予这个命令一个任务号码,还有这个任务触发的PID,这时候我们可以继续运行bash,同样这个任务无法被[ctrl]+[c]终止。

1
2
[root@localhost ~]# yum update &
[1] 71921

但是如果在后台中执行的命令有stdout或者stderr时,他的数据仍然会输出在屏幕上,所以我们无法掌握到前台任务,最佳的解决方法就是数据流重定向的方式:

1
2
3
4
5
[root@localhost ~]# yum upgrade > /tmp/log.txt 2>&1 &
[1] 71998
[root@localhost ~]# ls
anaconda-ks.cfg
[1]+ Done yum upgrade > /tmp/log.txt 2>&1

ctrl-z

将正在执行的任务丢到后台中暂停

jobs

查看当前的后台任务状态,可以知道目前有多少任务在后台当中,如果想要知道该iob的PID号码,加上-l参数即可,+代表最近被放到后台的任务号码,-代表最近第二个被放置到后台的任务号码,第三个及以后就不会有符号。

fg

可以将后台的任务拿到前台来处理

1
2
3
fg   代表将后台默认的带+号的任务拿到前台
fg - 代表将后台带-号的任务拿到前台
fg n 代表将和后台n号任务拿到前台

bg

ctrl-z可以让目前的任务丢到后台去暂停,如何让一个任务在后台下面运行,直接执行bg加上任务号码即可‘

kill

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
-l  列出所有的信号
-1 重新读取一遍参数的配置文件
-2 代表由键盘输入ctrl-c的操作
-9 立刻强制删除一个任务
-15 以正常方式终止一个任务

[gard3nia@localhost hack]$ jobs
[1]+ Stopped vim hack.txt
[gard3nia@localhost hack]$ kill -9 %1

[1]+ Stopped vim hack.txt
[gard3nia@localhost hack]$ jobs
[1]+ Killed vim hack.txt
[gard3nia@localhost hack]$ jobs
[gard3nia@localhost hack]$

kill后面默认加的是PID,所以想要kill掉bash的任务,必须要使用%+数字的这种方法

脱机管理

上述的后台指的是bash后台而不是系统后台,所以任务管理的后台与终端有关,如果在用远程连接的方式连接时,将任务一&的方式放到后台去,在任务尚未执行结束的时候脱机了,这时该任务不会再继续执行。

这时候就需要用到nohup命令,这个命令可以在脱机或者注销系统后,让系统继续执行

1
nohup + cmd + &

不过这个命令只并不支持bash的内置命令,所以cmd必须要是外置命令才行

进程管理

查看进程

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

ps

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

1
2
3
4
5
6
7
-A 将所有的进程全部显示出来,和-e效果一样
-a 不显示与终端有关的所有进程
-u 显示与使用者相关的进程
x 通常与a这个参数一起使用,可以列出比较完整的信息
l 较长,较详细的将该PID的信息列出
j 任务的格式
-f 更完整的输出
  • 查看自己的bash相关进程:ps -l

    1
    2
    3
    4
    [gard3nia@localhost hack]$ ps -l
    F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD
    0 S 1000 72017 72016 0 80 0 - 28925 do_wai pts/0 00:00:00 bash
    0 R 1000 72321 72017 0 80 0 - 38312 - pts/0 00:00:00 ps

    下面对这些参数做一个解释:

    F:代表进程表示,说明这个进程的权限,常见号码:

    • 4表示进程权限为root
    • 1表示此子进程仅仅执行fork而没有实际执行

    S:代表这个进程的状态:

    • R:running表示正在运行
    • S:sleep表示正在睡眠状态,可以被唤醒
    • D:不可被唤醒的状态,可能正在等待I/O状态
    • T:停止状态
    • Z:僵尸状态,进程已经终止但是却无法被删除至内存外

    ID:不解释

    C:cpu的使用率

    PRI/NI:代表此进程被CPU执行的优先级,越小代表越快被cpu执行

    ADDR:指出该进程在内存的那个部分,如果是running就会显示【-】

    SZ:代表该进程用掉多少内存

    WCHAN:表示目前进程是否运行

    TTY:登录者的终端位置

    TIME:使用cpu的时间

    CMD:表示触发该进程的命令

  • 查看系统所有的进程:ps aux

    USER:该进程属于所属用户的账号

    %MEM:该进程所占用的物理内存百分比

    VSZ:该进程使用掉虚拟内存的量

    RSS:该进程占用的固定的内存量

  • 显示出所有进程:ps -lA

    输出情况和ps -l相同,但是列出系统所有进程

  • 显示进程树:pstree

  • 僵尸进程

    造成僵尸进程的原因就是,该进程已经执行完毕,或者是应该要终止了,但是该进程的父进程却无法完整地将该进程结束掉,造成该进程一直在内存当中,在cmd后面加上了defunct。

top

相对于ps只能选取一个时间点的进程状态,top可以持续检测进程运行的状态,top的功能非常多,以下列出几个常用的参数和用法:

1
2
3
4
-d 整个进程界面更新的秒数,后面接秒数
-b 以批量的方式来执行top
-n 与-b搭配,意义是需要执行几次top的输出结果
-p 指定某些PID来执行查看检测

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

1
2
3
P 按照cpu的使用顺序排列
N 以PID来排序
q 退出

pstree

1
2
3
4
-A 各进程树之间的链接以ascii字符来链接
-U 各进程树之间以unicode字符来连接
-p 同时列出每个进程的PID
-u 同时列出每个进程的所属账号名称

主要的作用就是查找进程之间的相关性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
[gard3nia@localhost hack]$ pstree
systemd─┬─NetworkManager─┬─dhclient
│ └─2*[{NetworkManager}]
├─auditd───{auditd}
├─chronyd
├─crond
├─dbus-daemon───{dbus-daemon}
├─dockerd-current─┬─docker-containe───7*[{docker-containe}]
│ └─8*[{dockerd-current}]
├─firewalld───{firewalld}
├─login───bash
├─lvmetad
├─master─┬─pickup
│ └─qmgr
├─nginx───nginx
├─polkitd───6*[{polkitd}]
├─rsyslogd───2*[{rsyslogd}]
├─sshd───sshd───sshd───bash─┬─pstree
│ └─vim
├─systemd-journal
├─systemd-logind
├─systemd-udevd
└─tuned───4*[{tuned}]

由pstree的输出可以很清楚的看出所有的进程都是依附在systemd这个进程下面的,仔细一看,systemd的PID是1号,因为他是linux内核主动调用的第一个进程,所以为1号。这也是为什么出现僵尸进程的时候需要重新启动,因为systemd需要重新启动。

进程的管理

进程之间是可以相互控制的,进程之间如何相互管理?其实是通过给予该进程一个信号去告知该进程你想要它做什么。通过kill -l可以去查询信号的种类,需要记住的是1,9和15,那么如何发送一个信号给某个进程呢?就通过kill或者killall

1表示sighup,启动被终止的进程,可以让PID查询读取自己的配置文件,类似重新启动

9表示sigkill,代表强制结束一个进程的执行

15表示sigterm,代表以正常的方式结束进程,后续的操作会将该进程完成

kill

上面已经叙述过具体的用法,默认接的是进程的PID,如果需要管理bash任务,则需要加上%

killall

由于kill后面必须要加上PID,所以,通常kill都会配合ps或者top,pstree等命令,因为我们必须要寻找那个需要结束的进程的PID,这样很麻烦。现在killall可以直接利用执行命令的名称来给予信号。

1
2
-i 产生交互,如果需要删除,则会提醒用户
-I 命令名称忽略大小写

关于进程的执行顺序

由于存在关键和不关键的进程,所以需要设置进程的优先级

PRI和Nice

PRI是由内核动态调整的,所以我们无法干涉太多,只需要知道数值越小越先被执行,如果需要调整进程的优先级,就需要用到NI,一般来说:

1
PRI(new)=PRI(old)+NI

nice的值是有正负的,所以将nice的值降为负的,就会降低PRI的值,即会变得优先被处理

  • nice的范围为-20~19
  • root可以随意调整自己或者他人的nice值
  • 一般用户只可以调整自己的nice值,范围为0~19
  • 一般用户只可以将nice值越调越高

也就是说,如果需要调整某个进程的优先级,就是调整该进程的nice值,就需要用到nice或者renice命令

nice

新执行的命令即给予新的nice值,接上-n即可赋值

renice

已存在进程的nice值重新调整,直接加上nice值即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[gard3nia@localhost ~]$ sudo renice -3 1710
[sudo] password for gard3nia:
1710 (process ID) old priority 0, new priority -3
[gard3nia@localhost ~]$ ps -l
F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD
0 S 1000 1689 1688 0 80 0 - 28895 do_wai pts/1 00:00:00 bash
0 T 1000 1710 1689 0 77 -3 - 37305 do_sig pts/1 00:00:00 vim
0 R 1000 1719 1689 0 80 0 - 38312 - pts/1 00:00:00 ps
[gard3nia@localhost ~]$ kill -9 1710
[gard3nia@localhost ~]$ ps -l
F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD
0 S 1000 1689 1688 0 80 0 - 28895 do_wai pts/1 00:00:00 bash
0 R 1000 1720 1689 0 80 0 - 38312 - pts/1 00:00:00 ps
[1]+ Killed vim 1.txt

查看系统资源信息

free

查看内存的使用情况

1
2
3
4
-b bytes
-m mbytes
-k kbytes
-g gbytes

uname

1
2
3
4
5
6
-a 所有相关参数列出
-s 系统内核名称
-r 内核版本
-m 硬件架构
-p cpu类型
-i 硬件平台

uptime

显示目前系统已经运行的时间

netstat

追踪网络或者socket文件,该命令经常被用于网络监控方面,netstat的输出分为两大部分:分别是网络与系统自己的进程相关部分,相关参数如下

1
2
3
4
5
6
-a 将目前系统上所有的连接,监听,socket信息列出
-t 列出TCP网络数据包的信息
-u 列出udp网络数据包的信息
-n 以端口号来显示
-l 列出目前正在网络监听的端口
-p 列出该网络服务的pid

经常使用的方法:

1
2
3
4
5
6
7
8
9
10
[root@localhost ~]# netstat -tulnp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 1185/nginx: master tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 1171/sshd
tcp 0 0 127.0.0.1:25 0.0.0.0:* LISTEN 1267/master
tcp6 0 0 :::22 :::* LISTEN 1171/sshd
tcp6 0 0 ::1:25 :::* LISTEN 1267/master
udp 0 0 0.0.0.0:68 0.0.0.0:* 979/dhclient
udp 0 0 127.0.0.1:323 0.0.0.0:* 753/chronyd
udp6 0 0 ::1:323 :::* 753/chronyd

这样可以去检测我们的哪些进程开启了哪些网络端口,除了可以列出监听网络的界面和状态以外,最后一个栏目还可以显示此服务的PID以及进程的名称

SELinux

日后再来…

Author: Gard3nia
Link: https://gardenia30.top/2019/11/16/Linux基础学习笔记-进程管理/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.