Bootstrap

系统进程与计划任务

目录

1. 系统进程

1.1 什么是进程

1.2 进程管理命令

1.2.1 ps命令

1.2.2 top命令

1.2.3 pgrep命令

1.2.4 pstree命令

1.2.5 jobs命令

1.2.6 kill命令

kill

killall

pkill

2. 计划任务

2.1 一次性计划任务at

2.2 周期性计划任务crontab


那天开会的时候,发现孟哥的电脑风扇一直在高速旋转,而且看他分享屏幕的时候,编辑在线文档卡到飞起,撇了一眼协助编辑的人也不是很多,而且这个项目才刚刚开始,这么卡,我猜老孟这电脑怕不是这一周都没休息过,里面堆积了很多进程。也难怪,老孟平时忙的要命,有时候弄东西弄到一半就被喊去开会或者要忙别的事,哪来时间打理电脑。现在打开他的电脑任务管理器,估计内存已经爆了,被进程占满了。说到这就想到,好像还没有写过关于Linux系统进程的博客,索性和大家分享分享,自己也学习学习。

1. 系统进程

1.1 什么是进程

既然要学习如何管理进程,那么我们首先要知道什么是进程。

进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配的基本单位,是操作系统结构的基础,进程是程序的实体,是对运行中的程序的抽象(此词条解释来源百度)。

开发人员通过编写代码,将他们打包起来组成一个程序,当我们打开一个程序的时候,系统内核便会为它分配资源,每个进程都有系统给他分配的地址空间和cpu时间(cpu在处理这个进程上花的时间),用易理解的话来说,程序是“死”的,处理器赋予它生命,它就“活”了,进程其实就是执行中的程序。

知道了什么是进程,我们便可以继续铺开来说线程,线程是操作系统能够运算调度的最小单位,它被包含在进程之中,一个进程可以有多个线程,执行不同的任务,多个线程共享进程的全部资源。比如我们平时使用微信或者QQ聊天,打开了多个会话窗口,进程就将它分为多个线程放在多核处理器当中并行操作,避免了一个处理器在线程之间来回切换。

当然,线程和子进程是不一样的,每个子进程处于独立的空间,不共享进程的全部资源,就拿我们的浏览器来说,我们打开了Microsoft Edge,这时候浏览器会由程序变为进程,有一个主进程,负责管理所有窗口和标签页,处理用户界面、网络请求等。然后我们打开很多额外的标签页,这些标签页就属于浏览器的子进程,这些子进程互不干扰,假如我看b站,卡死了,但是我旁边的百度照样搜东西(除非主进程卡死了),浏览器正常运行。

但是,换成线程就不行了,比如你在打lol,进程分为多线程来处理任务,比如图形渲染、游戏逻辑计算、声音处理、玩家输入等,假如图形渲染这个线程挂了,那你肯定是玩不了了,而且整个游戏就会报错,所以现在开发者都会设计异常处理机制,捕获处理一些线程异常,所以有的时候会出现一些bug(指进程方面的bug),但不会整体崩溃。

1.2 进程管理命令

知道了什么是进程之后,我们要学会如何管理系统中的进程,在Linux操作系统中,我们可以通过这些常用的命令来实现对进程的查看、监测与管理。

1.2.1 ps命令

ps命令用于显示当前运行进程的状态信息

常用的参数

-a:显示当前终端下的所有进程信息,包括其他用户的进程。与“x”选项结合时将显示系统中所有的进程信息。

-u:使用以用户为主的格式输出进程信息。

-x:显示当前用户在所有终端下的进程信息。

ps命令通常不会使用一个单独的参数,一般直接用 ps -aux 组合使用来显示系统上所有正在运行的进程的详细信息

上述输出信息中,第一行为列表标题,其中各字段的含义描述如下

USER:运行该进程的用户名

PID:进程的唯一标识符,进程ID

%CPU:CPU占用的百分比。

%MEM:内存占用的百分比。

VSZ:该进程使用的虚拟内存量(KB)。

RSS:该进程占用的物理内存量(KB)。

TTY:表明该进程在哪个终端上运行。不是从终端启动的进程则显示为?。

STAT:该进程的状态(包括 :D:不可中断的休眠状态:R:正在运行状态;S:处于休眠状态,可被唤醒;T:停止状态,可能是在后台暂停或进程处于跟踪调试状态: Z:僵尸进程,进程已经中止,但是部分程序还在内存当中)

START:启动该进程的时间。

TIME:进程已经消耗CPU的时间

COMMAND:启动进程的命令名称和参数

STAT(进程状态)那一列,有些进程后面还有字符,这些字符表示:

<: 表示进程运行在高优先级上

N: 表示进程运行在低优先级上

L: 表示进程有页面锁定在内存中

s: 表示进程是控制进程

l: 表示进程是多线程的

+: 表示当前进程运行在前台(这里有前台那肯定有后台,在命令后面加上&可以将操作直接放至后台,如后台复制光盘镜像可以用cp /dev/cdrom /home/cetos7.iso &)

D:系统守护进程

下面我们来尝试改变一个进程的状态,并查看验证。

首先我们双击连接,重新打开一个终端,称为终端ZDB,在此终端vim a.txt 编辑一个文件

这时候我们回到第一个终端,下面称为ZDA,然后我们输入

ps -aux | grep a.txt       查看a.txt 的进程状态

现在我们回到ZDB然后按ctrl z 停止,这时候在ZDA再次输入ps -aux | grep a.txt

我们可以看到

这里解释一下 ctrl c 是发送 SIGINT 中断信号,通常会导致程序停止运行并返回到命令提示符; ctrl z 是发送 SIGSTOP 信号,挂起一个正在前台运行的进程,将作业放置到后台(暂停) ;ctrl d ,代表告诉终端,输入已经完成或者注销当前会话。

所以在系统出现问题时,我们可以用ps -aux快速查看当前正在运行的进程,帮助确定是否有异常进程或者占用资源过多的进程。

除了ps -aux还有ps -elf ,这个命令的意思是以长格式显示系统中的进程信息,包含了更多字段

这里出现了一些和 -aux不太一样的字符,它们的含义是

F:内核分配给进程的系统标记

S:进程的状态

PPID:父进程的进程号(如果没有明确的父进程,那么一般就是init进程,PID为1)

C:CPU使用的累计时间

PRI:进程的优先级(越大的数字代表越低的优先级)

NI: 优先级的调整值

ADDR:进程的内存地址

SZ:假如进程被换出,所需交换空间的大致大小

WCHAN:若该进程在睡眠,则显示睡眠中的系统函数名

STIME:进程启动时的系统时间

CMD:进程的启动命令

所以,ps -elf 命令一般用来查看和管理进程,以及如何通过分析进程信息来优化系统性能

1.2.2 top命令

那万一我想看一看某一个进程,在运行的时候,占用了多少系统资源,总不能一个终端运行,一个终端一直输入命令 ps -aux 吧。

这时候我们就可以使用 top 命令,top命令提供了实时动态更新的进程列表和资源使用情况,可以方便地监控系统当前的状态,而且还提供了一个交互式界面,允许用户根据需求调整进程排序,还可以调整刷新时间,默认为3秒刷新一次。

我们在终端中输入top

可以看到,一堆字符,我们逐个剖析

第一行分别为:

17:42:36  代表当前时间;

up 2:39系统运行时间 ,说明此服务器连续运行两个小时39分钟了;

4 users 当前登录用户数;

load average  系统负载,即任务队列的平均长度;

第二行系统任务(Tasks)信息分别为:

total,总进程数;

running,正在运行的进程数;

sleeping, 休眠的进程数;

stopped,停止的进程数;

zombie,僵尸进程数;

%Cpu(s) 代表CPU 占用信息:us,用户占用;sy,内核占用;ni,优先级调度占用;id,空闲CPU;wa,I/O 等待占用;hi,硬件中断占用;si,软件中断占用;st,虚拟化占用。要了解空闲的 CPU 百分比,主要看%id 部分。

KiB Mem 代表内存占用(Mem)信息:total,总内存空间;free,空闲内存;used,已用内存;buff/cache,物理内存和交换内存的缓冲区总和。

KiB Swap 代表交换空间(Swap)占用:total,总交换空间;free,空闲交换空间;used,已用交换空间;avail Mem,可用物理空间。

VIRT和VSZ  都表示进程占用的虚拟内存大小

RES和RSS  都表示进程实际使用的物理内存大小

SHR:共享内存大小

其他的与ps -aux和ps -elf 命令输出的字段含义差不多

下面我们来进行实验。

首先我们在ZDA执行top

然后我们去ZDB执行   dd if=/dev/zero of=/a.txt count=10 bs=100M

(这里注意不要设置太大,不然系统可能会卡死,进程将内存占满,有的时候远程连接会中断。

这里我们看到,我的磁盘空间还剩2.1G,然后我依然执行了创建20G文件的命令,提示写入错误。这里我们直接去虚拟机终端操作,因为还是存在远程连接都中断的情况的。

可以看到 / 目录已经被塞满爆红了。

使用 rm -rf /a.txt 命令强制删除a.txt

删除后我们查看一下,系统内存仍然不足,需要清理系统缓存和临时文件:

sync

echo 3 > /proc/sys/vm/drop_caches

可以发现,被占用的空间恢复了。

(注:所有操作都是管理员账户执行

然后我们接着上面说,创建了1GB文件后,回到ZDA我们就可以看到dd这个命令的CPU使用率一下子窜上来了,有的虚拟机可能创建的时候分配的cpu比较强,这里可以适当的增大创建的文件。

可能你们在操作的时候眼睛已经贴到屏幕上了也没找到CPU占用率很大的进程,因为我在top界面按了 P  键。因为 top 命令界面中可以通过按键对特定数值进行排序查看

P 按CPU使用率降序排序

M 按内存使用率降序排序

T 按运行时间长短降序排序

N 按进程ID升序排序

R 按照内存大小降序排列

H 按照线程数量降序排列

K 按照优先级降序排列

数字键 1:显示每个内核的 CPU 使用率 (升序)

U:指定显示的用户 (字母顺序)

h:可以获得 top 程序的在线帮助信息

q:键可以正常地退出 top 程序

上面我们提到,默认 3s 刷新一次,在top命令交互界面下按 s 修改刷新时间按空格 :立即刷新,输入数字就是多少秒。

注:若通过 top 排名工具发现某个进程 CPU 占用率非常高,需要终止该进程的运行,可以在 top 操作界面中按 k 键,然后在列表上方将会出现如下提示信息

根据提示输入指定进程的 PID 号并按 Enter 键, 出现二次确认的提示信息,然后继续按Enter 键确认即可终止对应的进程。

1.2.3 pgrep命令

grep命令是用来查找内容包含指定内容的文件,如果发现某文件的内容符合所指定的内容, grep 命令会把含有所需内容的那一行显示出来

所以,我们可以大概的猜测一下,pgrep命令的作用

pgrep 可以根据进程的名称或其他属性来查找并列出匹配的进程ID

pgrep -l:可同时输出对应的进程名以及PID

比如这里我们输入 pgrep -l 1        

可以看到,所有进程id或者进程名字中带有数字 1 的进程都被列了出来

-U:选项查询特定用户的进程

-t:选项查询在特定终端运行的进程

1.2.4 pstree命令

现在,假如我们需要查看一些进程之间的关系,主要是他们的父子关系和依赖关系,我们就可以用 pstree 命令,它会以树状结构的形式展示系统中运行的进程及其关系

-p:选项使用时可以同时列出对应的PID号

pstree [选项] [进程ID]

-u:选项可以列出对应的用户名

pstree [选项] [用户名]

-a:选项可以列出完整的命令信息

通常直接用 pstree -aup 组合起来使用,可以查看当前系统所有进程的进程树,包括各进程对应的PID 号、用户名、完整命令等信息。

1.2.5 jobs命令

jobs命令用于查看管理当前前台和后台的进程

用法是直接输入,如果有相应的进程会显示出来

-l:选项可以同时显示该进程对应的进程号

可以用 fg 加上前面的序号   将该进程放至前台

同样的 bg 加上见面的序号  将该进程放至后台

注意是进程前面的序号,不是进程号

+ 代表当前默认的作业

- 代表默认作业下一个作业

1.2.6 kill命令
kill

那么,我们只知道怎么查看,反复的查看,想要关掉这些进程,该怎么做呢?

我们可以使用kill 命令,来杀死进程,用法是

kill [选项] [进程号]

kill -15 请求进程终止(此选项为默认选项)

-1   挂起

-2   中断

-19 停止进程的执行

-18 继续执行已停止的进程

当我们对一些程序进行操作后,发现该进程已经无法响应终止信号,则可以结合“-9” 选项强行终止进程。

kill 3459 尝试正常结束进程

但发现进程并未退出

这时候我们用 kill -9 3549   强制终止目标进程,然后我们再来查看,可以看到进程已经被残忍的杀死了。

killall

然后,当需要结束系统中多个相同名称的进程时,使用 killall 命令将更加方便,效率更高。killall 命令同样也有“-9”选项,用法和kill差不多,但是多了一个字母选项

killall [选项] [进程]

-e:要求进程名称完全吻合

-I :不区分大小写

-v:显示详细输出

字母选项可以和数字选项结合使用,如我们不区分大小写,强制杀死两个 vim 进程

pkill

pkill 命令可以根据进程的名称、运行该进程的用户、进程所在的终端等多种属性终止特定的进程,用法与 killall 命令类似,但选项更加灵活,如

-U :指定用户

-t :指定终端

-e :列出所有被杀死的进程

-n :只杀死最近启动的匹配进程

其他就不一一举例了 --help 可自行查看,pkill命令主要就是用于杀死指定用户或终端的进程。

如,要终止由用户 zhangsan启动的进程,可以执行以下操作。

在终端B上创建用户zhangsan ,  vim t1 &      后台运行vim

然后我们回到终端 A,

pgrep –l -U "zhangsan"   先查看zhangsan这小子正在后台搞什么

pkill -9 -U "zhangsan"     管他干什么肯定没干好事,直接给他全部禁止

pgrep -l -U "zhangsan"    再查看一下,万一有活着的要补枪。

然后我们回到zhangsan那边,突然

画面变成这样了,什么都操作不了了,我们成功杀死了zhangsan的进程

2. 计划任务

进程都讲了,顺便说一下如何在指定的时候关闭或开启一些进程。

有些时候我们可能在特定的时间进行一些操作,但是好巧不巧,那个时间点我们恰好有事情要处理,但是这个操作又不得不执行,面对这种两难的情况,我们就需要用到计划任务,即在指定的时间让系统进行指定的操作。

2.1 一次性计划任务at

使用at命令设置的计划任务只在指定的时间点执行一次,需要注意的是,计划执行任务的时间、日期必须安排在当前系统的时刻之后, 否则将无法正确设置计划任务。

设置一次性计划任务时,在 at 命令行中依次指定计划执行任务的时间、日期作为参数 (若只指定时间则表示当天的该时间,若只指定日期则表示该日期的当前时间)

at命令的用法过程大概是,

1:at [时间(格式:xx:xx)] [日期(格式:xxxx-yy-dd)]

2:回车后进入带“at>”提示符的任务编辑界面,每行设置一条执行命令,可以依次设置多条语句

3:最后按 Ctrl+D 组合键提交任务。所设置的命令操作将在计划的时间点被依次执行。

下面我们来举个例子实际操作一下。

设置在 2024 年 6 月 27 日的16:35 自动执行以下任务:统计该时间点系统中由 root 用户运行的进程的数量,并将该数值保存到/opt/ps.root 文件中。ps:现在是北京时间2024.6.27 16:32

at 16:23 2024-06-27

at> pgrep -U root | wc -l > /opt/ps.root           任务设置完毕后按Ctrl+D 组合键提交

这时候我们查看ps.root会提示没有这个文件,别着急,让子弹飞一会,待到山花烂漫时,文件就在灯火阑珊处

再看一下,有啦有啦

下班后人先走机器开着再装一会,领导问到就说上厕所去了,然后九点半再关机,也可以用计划任务来操作。

at 21:30

at> shutdown -h now

at> <EOT>

然后ctrl d 提交

对于已经设置但还未执行的计划任务,可以通过 atq 命令进行查询。已执行过的任务将不会再出现在列表中。

若要删除指定编号的计划任务,可以使用 atrm 命令。删除后的任务将不会被执行,并且不会显示在 atq 命令的结果中,已经执行过的任务无法删除,毕竟它都不会显示的...

于是我们发现,删除后在查看就无了,真是个相当伟大的发现

2.2 周期性计划任务crontab

周期性计划任务约等于就是永久性计划任务了,设置周期性计划任务列表主要通过 crontab 命令进行,结合不同的选项可以完成不同的计划任务管理操作,常用的选项如下

-e:编辑计划任务列表。

-u:指定所管理的计划任务属于哪个用户,默认是针对当前用户(自己),一般只有 root 用户有权限使用此选项(用于编辑、删除其他用户的计划任务)。

-l:列表显示计划任务。

-r:删除计划任务列表。

这里特别讲一下周期性计划任务的时间设置,它是有顺序的,按照“分”“时”“日”“月”“周”的顺序依次设置。“*”代表任意值;“-”代表连续区间;“/”可以直接理解为'每',/5 意思是每五天;“,”用来表示不连续的区间。然后

分钟:0-59

小时:0-23

日期:1-31

月份:1-12

星期:0-7 (0 和 7 都表示星期日)

这么说可能有点抽象,好吧不是有点,是非常。但是,你得先大概看一下上面这些代表个啥。

然后我们来用例子讲一下

crontab -e    进入计划任务编辑表     (这个应该不难懂

然后我们来设置一个每天早上7:50自动开启 sshd 服务

50 7 * * * /usr/bin/systemctl start sshd.service            

你看,这个时间就是按照“分”“时”“日”“月”“周”的顺序排的,50是分钟,7是小时,就是七点五十,后面“日”“月”“周”都是“*”,说明什么?看看上面刚写的,“*”代表任意值,什么意思?顾名思义啊,就是随便哪天,随便哪一个月,随便周几,那不就是每天吗?

后面那一坨不管,就是代表着启动sshd服务,但是,它加了个路径,这是为什么呢?因各条计划任务在执行时并不需要用户登录,所以计划任务建议使用绝对路径,避免因缺少执行路径而无法执行命令的情况。

另外,在设置非每分都执行的任务时,“分”字段也应该填写一个具体的时间数值,而不要保留为默认的“*”,否则将会在每分钟执行一次计划任务。

下面再来个例子,每隔五天重启一下httpd服务

0 0 */6 * * /usr/bin/systemctl httpd restart

“分”“时”都是0,就是一天的0点0分,*/6就代表,每六天,无论哪一个月或者哪周几。

那如果我想要每周一、周三、周五的下午两点半重启一下httpd服务呢

30 14 * * 1,3,5 /usr/bin/systemctl httpd restart

这个应该不用再解释了吧

我们可以用crontab -l命令来查看用户的计划任务列表

对于 root 用户来说,还可以结合“-u”选项查看其他用户的计划任务,用法和刚才的pgrep差不多,很简单的,

crontab -l -u zhangsan    就可以知道zhangsan这小子肚子里装的什么坏水

crontab -r -u zhangsan    直接删除zhangsan的计划任务,让他中道崩殂

;