进程和内存管理
内核功用:进程管理、内存管理、文件系统、网络功能、驱动程序、安全功能等
cpu 没有空闲的概念,只有空转
进程是运行中的程序
-
Process: 运行中的程序的一个副本,是被载入内存的一个指令集合,是资源分配的单位
-
进程ID(Process ID,PID)号码被用来标记各个进程
-
UID、GID、和SELinux语境决定对文件系统的存取和访问权限
-
通常从执行进程的用户来继承
-
存在生命周期
进程创建:
-
init:第一个进程,从 CentOS7 以后为 systemd
-
进程:都由其父进程创建,fork(),父子关系,CoW:Copy On Write (读时共享,写时复制)
每个进程都有自己的资源,由操作系统分配,内存,栈,文件描述符
进程
进程是一个具有一定独立功能的程序在一个数据集上的一次动态执行的过程,是操作系统进行资源分配 和调度的一个独立单位,是应用程序运行的载体。进程是一种抽象的概念,从来没有统一的标准定义。
进程的组成:进程一般由程序、数据集合和进程控制块三部分组成。
程序用于描述进程要完成的功能,是控制进程执行的指令集;
数据集合是程序在执行时所需要的数据和工作区;
程序控制块(Program Control Block,简称PCB),包含进程的描述信息和控制信息,是进程存在的唯一 标志。
进程具有的特征:
动态性:进程是程序的一次执行过程,是临时的,有生命期的,是动态产生,动态消亡的;
并发性:任何进程都可以同其他进程一起并发执行;
独立性:进程是系统进行资源分配和调度的一个独立单位;
结构性:进程由程序、数据和进程控制块三部分组成。
线程
在早期的操作系统中并没有线程的概念,进程是能拥有资源和独立运行的最小单位,也是程序执行的最 小单位。任务调度采用的是时间片轮转的抢占式调度方式,而进程是任务调度的最小单位,每个进程有 各自独立的一块内存,使得各个进程之间内存地址相互隔离。
后来,随着计算机的发展,对CPU的要求越来越高,进程之间的切换开销较大,已经无法满足越来越复 杂的程序的要求了。于是就发明了线程。
线程是程序执行中一个单一的顺序控制流程,是程序执行流的最小单元,是处理器调度和分派的基本单 位。一个进程可以有一个或多个线程,各个线程之间共享程序的内存空间(也就是所在进程的内存空间)。
一个标准的线程由线程ID、当前指令指针(PC)、寄存器和堆栈组成。而进程由内存空间(代码、数据、进 程空间、打开的文件)和一个或多个线程组成。
进程与线程的区别
进程是操作系统分配资源的最小单位;
线程是程序执行的CPU调度的最小单位;
一个进程由一个或多个线程组成,线程是一个进程中代码的不同执行路线;
进程之间相互独立,但同一进程下的各个线程之间共享程序的内存空间(包括代码段、数据集、堆等)及一 些进程级的资源(如打开文件和信号),某进程内的线程在其它进程不可见;
调度和切换:线程上下文切换比进程上下文切换要快得多。
#查看进程中的线程
grep -i threads /proc/PID/status
#查看进程的二进制文件
ll /proc/PID/exe
#查看进程打开的文件
/proc/PID/fd/
并行和并发
进程结构
内核把进程存放在叫做任务队列(task list)的双向循环链表中
链表中的每一项都是类型为task_struct,称为进程控制块(Processing Control Block),PCB中包含一 个具体进程的所有信息
进程控制块PCB包含信息:
-
进程id、用户id和组id
-
程序计数器
-
进程的状态(有就绪、运行、阻塞)
-
进程切换时需要保存和恢复的CPU寄存器的值
-
描述虚拟地址空间的信息
-
描述控制终端的信息
-
当前工作目录
-
文件描述符表,包含很多指向file结构体的指针
-
进程可以使用的资源上限(ulimit –a命令可以查看)
-
输入输出状态:配置进程使用I/O设备
物理地址空间和虚拟地址空间
MMU:Memory Management Unit 负责虚拟地址转换为物理地址
程序在访问一个内存地址指向的内存时,CPU不是直接把这个地址送到内存总线上,而是被送到MMU (Memory Management Unit),然后把这个内存地址映射到实际的物理内存地址上,然后通过总线再 去访问内存,程序操作的地址称为虚拟内存地址
TLB:Translation Lookaside Buffer 翻译后备缓冲区,用于保存虚拟地址和物理地址映射关系的缓存
用户和内核空间
内存有一部份分配给内核使用,一部份分配给应用程序使用,分别称为内核空间和用户空间;
每个进程都包括5种不同的数据段
-
代码段:用来存放可执行文件的操作指令,也就是说是它是可执行程序在内存中的镜像。代码段需 要防止在运行时被非法修改,所以只准许读取操作,而不允许写入(修改)操作——它是不可写 的。
-
数据段:用来存放可执行文件中已初始化全局变量,换句话说就是存放程序静态分配的变量和全局 变量
-
BSS段:Block Started by Symbol”的缩写,意为“以符号开始的块,BSS段包含了程序中未初始化的 全局变量,在内存中 bss段全部置零。
-
堆(heap):存放数组和对象,堆是用于存放进程运行中被动态分配的内存段,它的大小并不固 定,可动态扩张或缩减。当进程调用malloc等函数分配内存时,新分配的内存就被动态添加到堆上 (堆被扩张);当利用free等函数释放内存时,被释放的内存从堆中被剔除(堆被缩减)。
-
栈(stack):栈是用户存放程序临时创建的局部变量,也就是说我们函数括弧“{}”中定义的变量 (但不包括static声明的变量,static意味着在数据段中存放变量)。除此以外,在函数被调用时, 其参数也会被压入发起调用的进程栈中,并且待到调用结束后,函数的返回值也会被存放回栈中。 由于栈的后进先出特点,所以栈特别方便用来保存/恢复调用现场。可以把堆栈看成一个寄存、交 换临时数据的内存区。
进程使用内存问题
内存泄漏:Memory Leak
指程序中用malloc或new申请了一块内存,但是没有用free或delete将内存释放,导致这块内存一直处 于占用状态。
内存溢出:Memory Overflow
指程序申请了10M的空间,但是在这个空间写入10M以上字节的数据,就是溢出。
内存不足:OOM
OOM 即 Out Of Memory,“内存用完了”,这种情况在java程序中比较常见。系统会选一个进程将之杀 死,在日志messages中看到类似下面的提示
vm.overcommit_memory 接受三种取值:
0: Heuristic overcommit handling. 这是缺省值,它允许overcommit,但过于明目张胆的 overcommit会被拒绝,比如malloc一次性申请的内存大小就超过了系统总内存。Heuristic的意思是“试 探式的”,内核利用某种算法猜测你的内存申请是否合理,它认为不合理就会拒绝overcommit。
1:Always overcommit,允许overcommit,对内存申请来者不拒。内核执行无内存过量使用处理。使 用这个设置会增大内存超载的可能性,但也可以增强大量使用内存任务的性能。
2:Don’t overcommit. 禁止overcommit。 内存拒绝等于或者大于总可用 swap 大小以及 overcommit_ratio 指定的物理 RAM 比例的内存请求。如果希望减小内存过度使用的风险,这个设置就 是最好的。
进程状态
进程的基本状态
创建状态:进程在创建时需要申请一个空白PCB(process control block进程控制块),向其中填写控制和 管理进程的信息,完成资源分配。如果创建工作无法完成,比如资源无法满足,就无法被调度运行,把 此时进程所处状态称为创建状态;
就绪状态:进程已准备好,已分配到所需资源,只要分配到CPU就能够立即运行;
执行状态:进程处于就绪状态被调度后,进程进入执行状态;
阻塞状态:正在执行的进程由于某些事件(I/O请求,申请缓存区失败)而暂时无法运行,进程受到阻塞。在满足请求时进入就绪状态等待系统调用;
终止状态:进程结束,或出现错误,或被系统终止,进入终止状态。无法再执行;
状态之间转换六种情况
运行——>就绪:1:主要是进程占用CPU的时间过长,而系统分配给该进程占用CPU的时间是有限的;
2:在采用抢先式优先级调度算法的系统中,当有更高优先级的进程要运行时,该进程就被迫让出CPU, 该进程便由执行状态转变为就绪状态;
就绪——>运行:运行的进程的时间片用完,调度就转到就绪队列中选择合适的进程分配CPU;
运行——>阻塞:正在执行的进程因发生某等待事件而无法执行,则进程由执行状态变为阻塞状态,如发 生了I/O请求;
阻塞——>就绪:进程所等待的事件已经发生,就进入就绪队列;
以下两种状态是不可能发生的:
阻塞——>运行:即使给阻塞进程分配CPU,也无法执行,操作系统在进行调度时不会从阻塞队列进行挑 选,而是从就绪队列中选取;
就绪——>阻塞:就绪态根本就没有执行,谈不上进入阻塞态;
进程更多的状态:
运行态:running
就绪态:ready
睡眠态:分为两种,可中断:interruptable,不可中断:uninterruptable
停止态:stopped,暂停于内存,但不会被调度,除非手动启动
僵死态:zombie,僵尸态,结束进程,父进程结束前,子进程不关闭,杀死父进程可以关闭僵死 态的子进程
僵尸进程
进程终止,父进程尚未回收,子进程残留资源(PCB)存放于内核中,变成僵尸(zombie)进程。
这样就会导致 如果进程不调用wait()或waitpid()的话,那么保留的那段信息就不会释放,其进程号就会 一直被占用,但系统所能使用的进程号是有限的,如果大量产生僵尸进程,将因为没有可用进程号而导 致系统不能产生新的进程,此即为僵尸进程的危害。
孤儿进程
如果在子进程在退出前,父进程先退出,这时子进程将成为孤儿进程,因为它的父进程已经死了。孤儿 进程会被PID=1的systemd进程收养,成为systemd的子进程。
注意,孤儿进程还会继续运行,而不会随父进程退出而终止,只不过其父进程发生了改变。
LRU 算法
LRU:Least Recently Used 近期最少使用算法(喜新厌旧),释放内存
内存淘汰策略,让进程自己能依据某种规则来管理内存空间,保证程序不会因为内存耗尽而无法工作
示例:假设序列为 4 3 4 2 3 1 4 2, 物理块有3个,则
第1轮 4调入内存 4
第2轮 3调入内存 3 4
第3轮 4调入内存 4 3
第4轮 2调入内存 2 4 3
第5轮 3调入内存 3 2 4
第6轮 1调入内存 1 3 2
第7轮 4调入内存 4 1 3
第8轮 2调入内存 2 4 1
IPC 进程间通信
同一主机:
pipe #管道,单向传输
socket #套接字文件,双工通信
Memory-maped file #文件映射,将文件中的一段数据映射到物理内存,多个进程共享这片内存
shm shared memory #共享内存
signal #信号
Lock #对资源上锁,如果资源已被某进程锁住,则其它进程想使用这些资源,都将被阻塞,直到锁被打开
semaphore #信号量,一种计数器
不同主机:socket=IP和端口号
RPC #remote procedure call
MQ #消息队列,生产者和消费者,如:Kafka,RabbitMQ,ActiveMQ
进程优先级
linux2.6内核将任务优先级进行了一个划分,实时优先级范围是0到MAX_RT_PRIO-1(0-99),而普通进程 的静态优先级范围是从MAX_RT_PRIO到MAX_PRIO-1(100-139)
优先级范围 | 描述 |
---|---|
0--99 | 实时进程 |
100--139 | 非实时进程 |
系统优先级:0-139, 数字越小,优先级越高,各有140个运行队列和过期队列
实时优先级: 99-0 值最大优先级最高
nice值:-20到19,对应系统优先级100-139
优先级越高,并不代表程序执行会更快,而是说在cpu调度时,给予更高的权重,最先执行
优先级决定的是执行顺序靠前,而不决定其程序本身要执行多久
示例:修改进程优先级
[root@ubuntu ~]# renice -n -10 3734
3734 (process ID) old priority 0, new priority -10
[root@ubuntu ~]# ps axo pid,cmd,nice | grep 3734
3734 ping www.baidu.com -10
#越界不会报错
[root@ubuntu ~]# renice -n -30 3734
3734 (process ID) old priority 0, new priority -20
示例:发起进程时直接指定优先级
[root@ubuntu ~]# nice -n 11 ping www.baidu.com
[root@ubuntu ~]# ps axo pid,cmd,nice | grep ping
3887 ping www.baidu.com
如果要设定某个程序的优先级,在启动时就直接指定,因为每次启动之后,PID的值都是不一样的
进程分类
操作系统分类:
-
协作式多任务:早期 windows 系统使用,即一个任务得到了 CPU 时间,除非它自己放弃使用CPU ,否则将完全霸占 CPU ,所以任务之间需要协作——使用一段时间的 CPU ,主动放弃使用。
-
抢占式多任务:Linux内核,CPU的总控制权在操作系统手中,操作系统会轮流询问每一个任务是 否需要使用 CPU ,需要使用的话就让它用,不过在一定时间后,操作系统会剥夺当前任务的 CPU 使用权,把它排在询问队列的最后,再去询问下一个任务。
进程类型:
-
守护进程: daemon,在系统引导过程中启动的进程,和终端无关进程
-
前台进程:跟终端相关,通过终端启动的进程
注意:两者可相互转化
按进程资源使用的分类:
-
CPU-Bound:CPU 密集型,非交互
-
IO-Bound:IO 密集型,交互
进程管理和性能相关工具
Linux系统状态的查看及管理工具:
pstree, ps, pidof, pgrep, top, htop, glance, pmap, vmstat, dstat, kill, pkill,
job, bg, fg, nohup
进程树 pstree
pstree 可以用来显示进程的父子关系,以树形结构显示
pstree [-acglpsStuZ] [ -h | -H PID ] [ -n | -N type ] [ -A | -G | -U ] [ PID | USER ]
#常用选项
-a|--arguments #显示该进程的完整指令及参数
-A|--ascii #使用 ASCII 字符绘制线条
-c|--compact #不压缩相同的子树
-h|--highlight-all #高亮显示当前进程及父进程
-H PID|--highlight-pid=PID #高亮显示指定进程及父进程
-g|--show-pgids #显示进程组ID,包含 -c 选项
-G|--vt100 #使用VT100线条绘制字符
-l|--long #不要截断长线
-n|--numeric-sort #根据PID排序显示
-N type|--ns-sort=type #根据指定规则排序(cgroup|ipc|mnt|net|pid|user|uts)
-p|--show-pids #显示PID,包含 -c 选项
-s|--show-parents #显示父进程
-S|--ns-changes #显示命名空间
-t|--thread-names #显示完整线程名称
-T|--hide-threads #不显示线程
-u|--uid-changes #显示进程切换
-Z|--security-context #显示selinux相关信息
进程信息 ps
ps: process state,可以查看进程当前状态的快照,默认显示当前终端中的进程,Linux系统各进程的相 关信息均保存在/proc/PID目录下的各文件中
ps [options]
#支持三种风格选项: UNIX选项 如 -A -e; GNU选项 如 --help; BSD选项 如 a
#常用选项
a #选项包括所有终端中的进程
x #选项包括不链接终端的进程
u #选项显示进程所有者的信息
f|--forest #选项显示进程树,相当于
k|--sort opt #属性 对属性排序,属性前加 - 表示倒序(--sort=uid,-ppid,+pid)
o #属性… 选项显示定制的信息 pid、cmd、%cpu、%mem
L #显示支持的属性列表
-C cmdlist #指定命令,多个命令用,分隔
-L #显示线程
-e #显示所有进程,相当于-A
-f #显示完整格式程序信息
-F #显示更完整格式的进程信息
-H #以进程层级格式显示进程相关信息
-u userlist|--user userlist #指定有效的用户ID或名称
-U userlist|--User userlist #指定真正的用户ID或名称
-g grplist|--group grplist #指定有效的gid或组名称
-G grplist|--Group grplist #指定真正的gid或组名称
-p pid #显示指pid的进程
--ppid pid #显示属于pid的子进程
-t ttylist #指定tty,相当于 t
-M #显示SELinux信息,相当于
#常用组合
#显示所有所有进程,并列出属主
ps aux
#显示所有所有进程,并列出属主
ps -ef
#详细格式显示所有进程
ps -eFH
#显示指定列
ps -eo pid,tid,class,rtprio,ni,pri,psr,pcpu,stat,comm
#显示指定列
ps -axo stat,euid,ruid,tty,tpgid,sess,pgrp,ppid,pid,pcpu,comm
#查询你拥有的所有进程
ps -x
#显示指定用户名(RUID)或用户ID的进程
ps -fU apache
ps -fU 48
#显示指定用户名(EUID)或用户ID的进程
ps -fu wang
ps -fu 1000
#查看以root用户权限(实际和有效ID)运行的每个进程
ps -U root -u root
#列出某个组拥有的所有进程(实际组ID:RGID或名称)
ps -fG nginx
#列出有效组名称(或会话)所拥有的所有进程
ps -fg mysql
ps -fg 27
#显示指定的进程ID对应的进程
ps -fp 1234
#以父进程ID来显示其下所有的进程,如显示父进程为1234的所有进程
ps -f --ppid 1234
#显示指定PID的多个进程
ps -fp 1204,1239,1263
#要按tty显示所属进程
ps -ft pts/0
#以进程树显示系统中的进程如何相互链接
ps -e --forest
#以进程树显示指定的进程
ps -f --forest -C sshd
ps -ef --forest | grep -v grep | grep sshd
#要显示一个进程的所有线程,将显示LWP(轻量级进程)以及NLWP(轻量级进程数)列
ps -fL -C nginx
#要列出所有格式说明符
ps L
#查看进程的PID,PPID,用户名和命令
ps -eo pid,ppid,user,cmd
#自定义格式显示文件系统组,ni值开始时间和进程的时间
ps -p 1234 -o pid,ppid,fgroup,ni,lstart,etime
#使用其PID查找进程名称:
ps -p 1244 -o comm= #要以其名称选择特定进程,显示其所有子进程
ps -C sshd,bash
#查找指定进程名所有的所属PID,在编写需要从std输出或文件读取PID的脚本时这个参数很有用
ps -C httpd,sshd -o pid= #检查一个进程的执行时间
ps -eo comm,etime,user | grep nginx
#排序,查找占用最多内存和CPU的进程
ps -eo pid,ppid,cmd,%mem,%cpu --sort=-%mem | head
ps -eo pid,ppid,cmd,%mem,%cpu --sort=-%cpu | head
#显示安全信息
ps -eM
ps --context
#使用以下命令以用户定义的格式显示安全信息
ps -eo euser,ruser,suser,fuser,f,comm,label
#使用watch实用程序执行重复的输出以实现对就程进行实时的监视,如下面的命令显示每秒钟的监视
watch -n 1 'ps -eo pid,ppid,cmd,%mem,%cpu --sort=-%mem | head'
ps 输出信息
字段 | 说明 |
---|---|
USER | 进程属主 |
PID | 进程ID |
PPID | 父进程ID |
%CPU | CPU占用率 |
%MEM | 内存占用率 |
VSZ | Virtual memory SiZe,虚拟内存集,线性内存,虚似内存 |
RSS | ReSident Size,常驻内存集,实际占用物理内存 |
TTY | 终端 |
STAT | 进程状态 |
START | 进程开始时间 |
TIME | 累计分配给进程的cpu时长 |
COMMAND | 对应的程序及参数 |
UID | 进程属主 |
C | cpu利用率,取整 |
STIME | 进程开始时间 |
CMD | 对应的程序及参数 |
ni | nice值 |
pri | priority 优先级 |
rtprio | 实时优先级 |
psr | processor CPU编号 |
进程状态字段说明
STAT字段 | 说明 |
---|---|
R | running ,运行中 |
S | interruptable sleeping,可中断的睡眠状态 |
D | uninterruptable sleeping,不可中断的睡眠状态 |
T | stopped,停止态 |
Z | zombie,僵尸态 |
+ | 前台进程 |
I,大写i | Idle kernel thread,CentOS 8 新特性 |
L | 内存分页并带锁 |
N | 低优先级进程 |
< | 高优先级进程 |
s | session leader,会话(子进程)发起者 |
I,小写L | 多线程进程 |
可中断睡眠和不可中断睡眠
可中断睡眠态的进程在睡眠状态下等待特定事件发生,即使特定事件没有产生,也可以通过其它手段唤醒该进 程,比如,发信号,释放某些资源等。
不可中断睡眠态的进程在也是在睡眠状态下等待特定事件发生,但其只能被特定事件唤醒,发信号或其它方法 都无效,发送给不可中断睡眠状态的进程的信号会被丢弃
查看进程信息 prtstat
可以显示进程信息,来自于psmisc包
此命令显的数据,都来自于 /proc/PID/ 目录,此命令加以整理,以格式化形式显示
prtstat [options] PID ...
#选项
-r|--raw #信息的原始显示
设置和调整进程优先级
进程优先级调整
-
静态优先级:100-139
-
进程默认启动时的nice值为0,优先级为120
-
只有根用户才能降低nice值(提高优先性)
nice命令
以指定的优先级来启动进程
nice [OPTION] [COMMAND [ARG]...]
#选项
-n|--adjustment=N #以指定优先级运行程序
renice命令
可以调整正在执行中的进程的优先级
renice [-n] priority pid...
#范例:设定进程优先级
[root@ubuntu ~]# nice -n -10 ping 127.0.0.1
#查看
[root@ubuntu ~]# ps axo pid,cmd,nice |grep ping
7981 ping 127.0.0.1 -10
7992 grep --color=auto ping 0
#范例:修改进程优先级
[root@ubuntu ~]# renice -n -20 7981
7981 (process ID) old priority -10, new priority -20
#查看
[root@ubuntu ~]# ps axo pid,cmd,nice |grep ping
7981 ping 127.0.0.1 -20
8082 grep --color=auto ping 0
搜索进程
进程搜索的常用命令:
ps options | grep 'pattern'
pgrep [options] pattern
/sbin/pidof COMMAND
pgrep
pgrep [options] pattern
#常用选项
-d|--delimiter <string> specify output delimiter
-l|--list-name #列出进程ID和进程名
-a|--list-full #显示详细完整的进程信息
-v|--inverse #取反
-w|--lightweight #显示线程ID
-c|--count #统计匹配到的进程数量
-f|--full #使用完整的进程名匹配
-g|--pgroup <PGID,...> #指定进程的属组作为条件
-G|--group <GID,...> #指定 real group IDs 作为条件
-P|--parent <PPID,...> #显示指定进程的子进程
-s|--session <SID,...> #根据会话ID显示
-t|--terminal <tty,...> #显示指定终端的进程
-u|--euid <ID,...> #指定 effective UIDs
-U|--uid <ID,...> #指定 real IDs,真实用户
-x|--exact #根据指定的命令匹配
-F|--pidfile <file> #从文件中读取PID作为条件
#示例
#普通用户发起passwd 进程
[jose@ubuntu ~]$ passwd
Changing password for user jose.
Current password:
#实际进程属主是root
[root@ubuntu ~]# ps aux | grep passwd
root 15440 0.0 0.4 331172 8564 pts/1 S+ 22:24 0:00 passwd
#查看user 和 ruser
[root@ubuntu ~]# ps axo pid,cmd,user,ruser
#根据 real user查找
[root@ubuntu ~]# pgrep -aU jose
2843 -bash
15440 passwd
pidof
查看相关命令的进程
pidof [options] [program [...]]
#常用选项
-s|--single-shot #多个结果时只显示一条
-x #按照脚本名称查找
-o|--omit-pid <PID,...> #不显示指定的pid
#示例
[root@ubuntu ~]# pidof bash
8274 8023 6925 994
#只显示一个进程号
[root@ubuntu ~]# pidof -s bash
8274
#按文件名查找
[root@ubuntu ~]# ./0528/ping.sh
[root@ubuntu ~]# pidof -x ping.sh
8629
[root@ubuntu ~]# ps aux | grep 8629
root 8629 0.0 0.4 222528 3200 pts/1 S+ 08:53 0:00 /bin/bash
./0528/ping.sh
#如果将文件名当bash的参数,则无法用-x 查找
[root@ubuntu ~]# bash ./0528/ping.sh
[root@ubuntu ~]# pidof -x ping.sh
#忽略某些pid
[root@ubuntu ~]# pidof httpd
1444 1436 1435 1428 1331
[root@ubuntu ~]# pidof -o 1444,1435 httpd
1436 1428 1331
负载查询 uptime
示例
[root@ubuntu ~]# uptime
08:55:54 up 11:03, 3 users, load average: 0.00, 0.01, 0.00
08:55:54 #系统当前时间
up 11:03 #系统己开机运行时长
3 users #当前有三个用户登录
load average: 0.00, 0.01, 0.00 #系统的平均负载,1分钟,5分钟,15分钟
#查看变化
[root@ubuntu ~]# ping -f 127.1
[root@ubuntu ~]# uptime
w命令
[root@ubuntu ~]# w
08:55:55 up 11:03, 3 users, load average: 0.00, 0.01, 0.00
USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT
root pts/0 10.0.0.1 Tue19 10:05m 0.33s 0.33s -bash
root pts/1 10.0.0.1 Tue20 10:31m 0.16s 0.12s -bash
root pts/2 10.0.0.1 08:40 3.00s 0.03s 0.00s w
系统平均负载:指在特定时间间隔内运行队列中的平均进程数,通常每个CPU内核的当前活动进程数不 大于3,那么系统的性能良好。如果每个CPU内核的任务数大于5,那么此主机的性能有严重问题。
如:linux主机是1个双核CPU,当Load Average 为6的时候说明机器已经被充分使用
显示CPU相关统计 mpstat
来自于sysstat包
mpstat [ options ] [ <interval> [ <count> ] ]
#常用选项
-P {cpu_list|ALL} #查看指定CPU,可以写成 0,1,2 0-
2 2-
-I {SUM|CPU|SCPU|ALL} #显示指定中断数
-o JSON #以JSON格式输出
示例
#查看当前主机所有cpu运行情况
[root@ubuntu ~]# mpstat
Linux 4.18.0-372.9.1.el8.x86_64 (rocky86.m51.magedu.com) 08/24/2022 _x86_64_
(2 CPU)
09:13:00 AM CPU %usr %nice %sys %iowait %irq %soft %steal %guest
%gnice %idle
09:13:00 AM all 0.73 0.01 0.49 0.35 0.92 0.30 0.00 0.00
0.00 97.19
#查看第一颗cpu运行情况
[root@ubuntu ~]# mpstat -P 0
Linux 4.18.0-372.9.1.el8.x86_64 (rocky86.m51.magedu.com) 08/24/2022 _x86_64_
(2 CPU)
09:13:37 AM CPU %usr %nice %sys %iowait %irq %soft %steal %guest
%gnice %idle
09:13:37 AM 0 0.75 0.01 0.48 0.00 0.89 0.26 0.00 0.00
0.00 97.61
#查看所有
[root@ubuntu ~]# mpstat -P ALL
Linux 4.18.0-372.9.1.el8.x86_64 (rocky86.m51.magedu.com) 08/24/2022 _x86_64_
(2 CPU)
05:11:23 PM CPU %usr %nice %sys %iowait %irq %soft %steal %guest
%gnice %idle
05:11:23 PM all 0.16 0.00 0.23 0.68 0.22 0.10 0.00 0.00
0.00 98.61
05:11:23 PM 0 0.17 0.00 0.25 0.00 0.22 0.11 0.00 0.00
0.00 99.25
05:11:23 PM 1 0.15 0.01 0.21 1.35 0.23 0.09 0.00 0.00
0.00 97.97
输出字段说明
%user #用户空间,应用程序占比
%nice #以nice优先级运行的进程用户态时间
%sys #内核空间,内核占比
%iowait #io等待占比
%irq #硬中断占比
%soft #软中断占比
%steal #虚拟化消耗占比
%guest #运行虚拟化主机cpu自身时间的占比
%gnice #运行虚拟cpu上的nice 进程的占比
%idle #空闲时间占比
查看进程实时状态 top 和 htop
top
top -hv | -bcEHiOSs1 -d secs -n max -u|U user -p pid(s) -o field -w [cols]
选项
-h|v #显示帮助
-b #显示全部所有进程
-c #显示命令信息
-E{k|m|g|t|p|e} #指定内存显示单位
-H #线程模式
-1 #十进制数字1,在首部分别显示每颗CPU信息
-p PID #显示指定进程的数据
-d N #指定刷新时间间隔,默认为3秒
-n N #刷新多少次后退出
-u|U user #查看指定用户的进程
-w cols #指定输出内容显示宽度
#常用组合:
#10s刷新一次
[root@ubuntu ~]# top -d 10
#显示指定用户的进程统计
[root@ubuntu ~]# top -u jose
#显示指定进程的线程
[root@ubuntu ~]# top -Hp 1444
#显示进程的具体命令
[root@ubuntu ~]# top -p 1331 -c
交互环境下子命令:
P #以CPU使用率排序,即 %CPU字段
M #以内存使用率排序,即 %MEM字段
T #以CPU使用时长排序,即 TIME+字段
1 #十进制数字1,在首部分开显示每颗CPU信息
l #小写L,是否显示首部top信息
t #切换首部tasks及cpu显示
m #切换首部内存信息显示
s #修改刷新时间间隔
k #终止指定进程
q #退出
h|? #显示帮助
首部CPU行字段说明:
us #用户空间
sy #内核空间
ni #调整nice时间
id #空闲
wa #等待IO时间
hi #硬中断
si #软中断(模式切换)
st #虚拟化消耗占比
htop
htop 是增强版的 top 命令,在 centos 中来自于 epel 源, ubuntu 中可以直接安装
htop [-dCFhpustvH]
#常用选项
-d N #指定刷新时间
-u user #仅显示指定用户的进程
-s colume #以指定字段进行排序
#子命令
s #跟踪选定进程的系统调用
l #显示选定进程打开的文件列表
a #将选定的进程绑定至某指定CPU核心
t #显示进程树
内存空间 free
free 可以显示内存空间使用状态
free [options]
#常用选项
-b|--bytes #以字节为单位显示
-k|--kibi #以kb为单位显示
-m|--mebi #以MB为单位显示
-g|--gibi #以GB为单位显示
--tebi #以TB为单位显示
--pebi #以PB为单位显示
-h|--human #以人类友好阅读的形式显示
--si #以1000为单位,而不是1024
-t|--total #添加统计行
-l|--lohi #显示峰值和谷值
-s N|--seconds N #每隔N秒刷新一次
-c N|--count N #输出N次后退出
#示例
[root@ubuntu ~]# free
total used free shared buff/cache available
Mem: 796020 340168 126040 2100 329812 324628
Swap: 1679356 473088 1206268
[root@ubuntu ~]# free -h
total used free shared buff/cache available
Mem: 777Mi 332Mi 123Mi 2.0Mi 322Mi 316Mi
Swap: 1.6Gi 462Mi 1.1Gi
字段说明
total #内存总量
used #已经使用的内存
free #空闲的内存
shared #多个进程共享的内存
buff/cache #缓冲和缓存使用的内存
available #可用内存
buffer / cache
缓冲(buffers) 是指在写磁盘时,先把要写的数据放入一个缓冲区,然后再批量写,以减少磁盘碎片和硬 盘反复寻道,从而提高系统性能
buffers 主要用于硬盘与内存之间的数据交互
缓存(cached) 是指文件的内容要被多个进程使用的时候,则可以将内容放入缓存区,则后续就可以直接 从内存中读,而不用再消耗IO
cached主要作用于CPU和内存之间的数据交互(本来要用IO读硬盘文件,现在变成了读内存)
向/proc/sys/vm/drop_caches中写入相应的修改值,会清理缓存。建议先执行sync(sync 命令将所有 未写的系统缓冲区写到磁盘中,包含已修改的 i-node、已延迟的块 I/O 和读写映射文件)。执行echo 1、2、3 至 /proc/sys/vm/drop_caches, 达到不同的清理目的。
如果因为是应用有像内存泄露、溢出的问题时,从swap的使用情况是可以比较快速可以判断的,但通过 执行free 反而比较难查看。但核心并不会因为内存泄露等问题并没有快速清空buffer或cache(默认值 是0),生产也不应该随便去改变此值。
一般情况下,应用在系统上稳定运行了,free值也会保持在一个稳定值的。当发生内存不足、应用获取 不到可用内存、OOM错误等问题时,还是更应该去分析应用方面的原因,否则,清空buffer,强制腾出 free的大小,可能只是把问题给暂时屏蔽了。
排除内存不足的情况外,除非是在软件开发阶段,需要临时清掉buffer,以判断应用的内存使用情况; 或应用已经不再提供支持,即使应用对内存的时候确实有问题,而且无法避免的情况下,才考虑定时清 空buffer。
清理缓存
[root@ubuntu ~]# cat /proc/sys/vm/drop_caches
0
[root@ubuntu ~]# free -h
total used free shared buff/cache available
Mem: 777Mi 332Mi 117Mi 2.0Mi 327Mi 316Mi
Swap: 1.6Gi 462Mi 1.1Gi
[root@ubuntu ~]# echo 3 > /proc/sys/vm/drop_caches
[root@ubuntu ~]# cat /proc/sys/vm/drop_caches
3
[root@ubuntu ~]# free -h
total used free shared buff/cache available
Mem: 777Mi 313Mi 385Mi 2.0Mi 78Mi 367Mi
Swap: 1.6Gi 461Mi 1.2Gi
进程对应的内存映射 pmap
查看进程的内存占用情况
pmap [options] PID [PID ...]
#常用选项
-x|--extended #显示详细信息
-X|-XX #显示更详细信息
-d|--device #显示设备
-q|--quiet #显示时不显示头尾
-p|--show-path #显示映射表中的完整路径
-A|--range=<low>[,<high>] #指定内存地址起始位置
#显示指定进程在内存中的占用情况
[root@ubuntu ~]# pmap 1331
[root@ubuntu ~]# pmap -x 1331
[root@ubuntu ~]# pmap -pd 1331
[root@ubuntu ~]# pmap -pd 1331 -A 00007f8531694000,00007ffca1ff8000
虚拟内存信息 vmstat
虚拟内存
虚拟内存是操作系统提供的一种内存管理技术,操作系统会为每个进程分配一套独立的,连续的,私有 的内存空间,让每个程序都以为自己独享所有主存的错觉,这样做的目的是方便内存管理。
程序所使用的内存是虚拟内存(Virtual Memory)
CPU使用的内存是物理内存(Physical Memory) MMU LTB
虚拟内存地址和物理内存地址之间的映射和转换由CPU中的内存管理单元(MMU)进行管理
vmstat [options] [delay [count]]
#常用选项
-a|--active #分开显示活动和非活动内存
-s|--stats #显示事件统计
-d|--disk #统计磁盘设备相关信息
-D|--disk-sum #综合统计磁盘
-p|--partition <dev> #统计指定分区
-S|--unit <char> #指定显示单位 k|K|m|M
-w|--wide #以宽格式显示
-t|--timestamp #显示时间
#示例
#显示当前时间点虚拟内存数据
[root@ubuntu ~]# vmstat
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
4 0 471808 375764 12 101288 4 16 87 27 100 198 1 1 98 0 0
#每秒显示一次
[root@ubuntu ~]# vmstat 1
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
3 0 471808 375764 12 101288 4 16 87 27 100 198 1 1 98 0 0
0 0 471808 375704 12 101288 0 0 0 0 96 183 0 1 99 0 0
0 0 471808 375524 12 101288 0 0 0 0 160 242 3 4 93 0 0
procs:
r #可运行(正运行或等待运行)进程的个数,和核心数有关
b #处于不可中断睡眠态的进程个数(被阻塞的队列的长度)
memory:
swpd #交换内存的使用总量
free #空闲物理内存总量
buffer #用于buffer的内存总量
cache #用于cache的内存总量
swap:
si #从磁盘交换进内存的数据速率(kb/s)
so #从内存交换至磁盘的数据速率(kb/s)
io:
bi #从块设备读入数据到系统的速率(kb/s)
bo #保存数据至块设备的速率
system:
in #interrupts 中断速率,包括时钟
cs #context switch 进程切换速率
cpu:
us #Time spent running non-kernel
code
sy #Time spent running kernel code
id #Time spent idle. Linux 2.5.41前,包括IO-wait time.
wa #Time spent waiting for IO. 2.5.41前,包括in idle.
st #Time stolen from a virtual machine. 2.6.11前, unknown.
统计CPU和设备IO信息 iostat
iostat 可以提供更丰富的IO性能状态数据
iostat [ options ] [ <interval> [ <count> ] ]
#常用选项
-c #只显示CPU行
-d #显示设备〈磁盘)使用状态
-k #以千字节为为单位显示输出
-h|--human #以方便阅读的方式显示
-t #在输出中包括时间戳
-x #在输出中包括扩展的磁盘指标
#示例
#显示当前时间节点磁盘数据
[root@ubuntu ~]# iostat
Linux 5.15.0-72-generic (ubuntu) 05/18/2023 _x86_64_ (2 CPU)
avg-cpu: %user %nice %system %iowait %steal %idle
1.57 0.06 1.12 0.02 0.00 97.23
Device tps kB_read/s kB_wrtn/s kB_dscd/s kB_read
kB_wrtn kB_dscd
dm-0 0.04 0.85 0.00 0.00 20880
0 0
#显示字段
tps #该设备每秒的传输次数,多个逻辑请求可能会被合并为一次I/O请求
kB_read/s #每秒从设备(drive expressed)读取的数据量;
kB_wrtn/s #每秒向设备(drive expressed)写入的数据量;
kB_read #读取的总数据量
kB_wrtn #写入的总数量数据量;这些单位都为Kilobytes。
监视磁盘I/O iotop
iotop命令是一个用来监视磁盘I/O使用状况的top类工具iotop具有与top相似的UI,其中包括PID、用 户、I/O、进程等相关信息,可查看每个进程是如何使用IO
iotop [OPTIONS]
#常用选项
-o|--only #只显示正在产生I/O的进程或线程,除了传参,可以在运行过程中按o生效
-b|--batch #非交互模式,一般用来记录日志
-n N|--iter=N #设置监测的次数,默认无限。在非交互模式下很有用
-d N|--delay=N #设置每次监测的间隔,默认1秒,接受非整形数据例如1.1
-p PID|--pid=PID #指定监测的进程/线程
-u USER|--user=USER #指定监测某个用户产生的I/O
-P|--processes #仅显示进程,默认iotop显示所有线程
-a|--accumulated #显示累积的I/O,而不是带宽
-k|--kilobytes #使用kB单位,而不是对人友好的单位。在非交互模式下,脚本编程有用
-t|--time #加上时间戳,非交互非模式
-q|--quiet #禁止头几行,非交互模式,有三种指定方式
-q #只在第一次监测时显示列名
-qq #永远不显示列名
-qqq #永远不显示I/O汇总
#交互式子命令:
left/right #改变排序列
r #反向排序
o #切换至选项--only
p #切换至--processes选项
a #切换至--accumulated选项
q #退出
i #改变线程的优先级
显示网络带宽使用情况 iftop
iftop -h | [-nNpblP] [-u unit] [-i interface] [-f filter code] [-F net/mask] [-G net6/mask6]
#常用选项
-h #显示帮助
-n #以IP的形式显示主机
-N #直接显示端口号,而不是服务名
-p #显示同一网段其它主机的流量
-b #不显示图形化的进度条
-B #以 bytes 为单位显示网络带宽
-a #以数据包为单位显示带宽
-i interface #指定监听的网卡
-F net/mask #只显示ipv4流量
-G net6/mask6 #只显示ipv6流量
-l #显示本地ipv6流量,默认关闭
-P #显示流量端口号
查看网络实时吞吐量 nload
nload [options] [devices]
#常用选项
-m #显示所有设备
-t N #数据刷新频率,单位毫秒,默认500
-u h|b|k|m|g|H|B|K|M|G #显示单位(h auto, b Bit/s, B
Byte/s)
-U h|b|k|m|g|H|B|K|M|G #总流量显示单位
devices #指定设备
#显示字段:
Curr #当前流量
Avg #平均流量
Min #最小流量
Max #最大流量
Ttl #总流量
查看进程网络带宽的使用情况 nethogs
NetHogs是一个开源的命令行工具(类似于Linux的top命令),用来按进程或程序实时统计网络带宽使 用率。
nethogs [-h] [-V] [-d] [-v] [-t] [-c] [-p] [-s] [device(s)]
#常用选项
-d #数据刷新时间间隔,默认1秒
-v #显示单位(0 KB/s|1 total KB|2 total B|3 total MB)
-t #跟踪显示
-s #按发送数据量排序
-a #显示所有设备数据,包含回环设备
device #指定设备
#交互式命令:
q #退出
s #根据发送数据量排序
r #根据接收数据量排序
m #切换显示单位
网络监视工具 iptraf-ng
来自于iptraf-ng包,可以进网络进行监控,对终端窗口大小有要求
iptraf-ng [options]
#常用选项
-i <iface> #指定网络设备,默认所有
-d <iface> #指定网络设备,显示详细信息
-s <iface> #指定网络设备,统计tcp和udp信息
-z <iface> #指定网络设备,统计数据包
-B #在后台执行
-f #清除所有锁和计数器
-t N #仅统计指定的时长,单位分钏
-L <logfile> #指定日志文件
系统资源统计 dstat
dstat由pcp-system-tools包提供,但安装dstat包即可, 可用于代替 vmstat,iostat功能
dstat [-afv] [options...] [delay [count]]
#常用选项
-c|--cpu #显示cpu相关信息
-C 0,3,total #指定显示项,cpu0,cpu3和总计
-d|--disk #显示磁盘信息
-D total,sda #指定显示项,sda和总计
--dm|--device-mapper #显示设备映射信息
--part|--partition #显示分区信息
-P total,sdb2 #显示指定分区信息
-g|--page #显示page相关统计数据
-m|--mem #显示memory相关统计数据
-n|--net #显示network相关统计数据
-N eth1,total #指定网络设备
-p|--proc #显示process相关统计数据
-r|--io #显示io相关统计数据
-s|--swap #统计swap信息
-S swap1,total #指定swap
--socket #显示所有socket信息
--tcp #显示所有tcp信息
--udp #显示所有udp信息
--vm #显示vm统计信息
--vm-adv #显示高级vm统计信息
--list #列出所有可用插件
--pluginName #启用插件
-o file|--output=file #将统计信息写到指定文件
-top-cpu #显示最占用CPU的进程
-top-io #显示最占用io的进程
-top-mem #显示最占用内存的进程
-top-latency #显示延迟最大的进程
综合监控工具 glances
CentOS 系统通过 epel 源安装,glances 可查看当前主机相关信息,也可运行于C/S模式查看远程主机信 息
glances [OPTIONS]
#常用选项
-b #以Byte为单位显示网卡数据速率
-d #关闭磁盘I/O模块
-f file #设定输入文件位置
-o {HTML|CSV} #输出格式
-m #禁用mount模块
-n #禁用网络模块
-t N #延迟时间间隔
-1 #每个CPU的相关数据单独显示
#查看当前主机
[root@ubuntu ~]# glances
#glances 运行于C/S模式
#服务端配置
glances -s -B IPADDR #指明监听在哪个IP上,默认端口为 tcp 61209
#客户端配置
glances -c IPADDR #连接指定的IP
查看进程打开文件 lsof
lsof:list open files,查看当前系统文件的工具。在linux环境下,一切皆文件,用户通过文件不仅可以 访问常规数据,还可以访问网络连接和硬件如传输控制协议 (TCP) 和用户数据报协议 (UDP)套接字等, 系统在后台都为该应用程序分配了一个文件描述符
lsof [options...] [names]
#常用选项
-c cmd #列出指定进程所打开的文件
-g #列出GID号进程详情
+d dir #列出目录下被打开的文件
+D dir #递归列出目录下被打开的文件
-n dir #列出使用NFS的文件
-i condition #列出符合条件的进程
-p pid #列出指定进程号所打开的文件
-u #列出UID号进程详情
-n #不反向解析网络名字
CentOS 8 新特性 cockpit
由cockpit包提供,当前Ubuntu和CentOS7也支持此工具
Cockpit 是CentOS 8 取入的新特性,是一个基于 Web 界面的应用,它提供了对系统的图形化管理
-
监控系统活动(CPU、内存、磁盘 IO 和网络流量)
-
查看系统日志条目
-
查看磁盘分区的容量
-
查看网络活动(发送和接收)
-
查看用户帐户
-
检查系统服务的状态
-
提取已安装应用的信息
-
查看和安装可用更新(如果以 root 身份登录)并在需要时重新启动系统
-
打开并使用终端窗口
安装,启动
[root@localhost ~]# yum install -y cockpit
[root@localhost ~]# systemctl enable --now cockpit.socket
Created symlink /etc/systemd/system/sockets.target.wants/cockpit.socket →
/usr/lib/systemd/system/cockpit.socket.
#在RHEL 9.2 及之后版本的新安装中禁用了远程 root 登录 WEB 控制台
#修改 /etc/cockpit/disallowed-users 文件,放行 root 用户,再重启 systemctl restart cockpit.socket
#访问
https://172.16.1.44:9090/
信号发送 kill
kill:内部命令,可用来向进程发送控制信号,以实现对进程管理,每个信号对应一个数字,信号名称以 SIG开头(可省略),不区分大小写
kill [-signal|-s signal|-p] [-q value] [-a] [--] pid|name...
kill -l [number] | -L
#常用选项
-SIGNAL #信号名称
-s #指定信号
-u uid #effective user,生效者
-U uid #real user,真正发起运行命令者
-t terminal #与指定终端相关的进程
-l|-L #显示信号名(pgrep可用),不跟进程则列出所有信号
-a #显示完整格式的进程名
(pgrep可用)
-P pid #显示指定进程的子进程
#常用信号
1) SIGHUP 无须关闭进程而让其重读配置文件
2) SIGINT 中止正在运行的进程;相当于Ctrl+c
3) SIGQUIT 相当于ctrl+\
9) SIGKILL 强制杀死正在运行的进程,可能会导致数据丢失,慎用!
15) SIGTERM 终止正在运行的进程,默认信号
18) SIGCONT 继续运行
19) SIGSTOP 后台休眠
按PID向进程发送信号:
kill [-s sigspec | -n signum | -sigspec] pid | jobspec ... or kill -l [sigspec]
#范例
kill -1 pid …
kill -n 9 pid
kill -s SIGINT pid
按程序名发送信号:
killall [-SIGNAL] comm…
#范例
killall nginx
按模式发送信号:
pkill [options] pattern
指定信号的方式:
-
使用信号的数字标识, 如 1,2,3
-
使用信号的完整名称,不区分大小写, 如 SIGHUP, sighup
-
使用信号的简写名称,不区分大小写,如 HUP,hup
作业管理
Linux的作业控制
-
前台作业:通过终端启动,且启动后一直占据终端
-
后台作业:可通过终端启动,但启动后即转入后台运行(释放终端)
让作业运行于后台
-
运行中的作业: Ctrl+z
-
尚未启动的作业: COMMAND &
后台作业虽然被送往后台运行,但其依然与终端相关;退出终端,将关闭后台作业。如果希望送往后台 后,剥离与终端的关系
-
nohup COMMAND &>/dev/null &
-
screen;COMMAND
-
tmux;COMMAND
Ctrl+z 使占据终端的进程暂停,让出终端
jobs可以查看当前终端所有作业
作业控制
fg [[%]JOB_NUM] #把指定的后台作业调回前台
bg [[%]JOB_NUM] #让送往后台的作业在后台继续运行
kill [%JOB_NUM] #终止指定的作业
并行运行
利用后台执行,实现并行功能,即同时运行多个进程,提高效率
方法
#方法一
cat all.sh
f1.sh&
f2.sh&
f3.sh&
wait
#方法二
f1.sh&f2.sh&f3.sh&
wait
计划任务
通过任务计划,可以让系统自动的按时间或周期性任务执行任务
注意: 学习本节需要实现邮件通知,学习内容前必须安装并启动邮件服务
环境准备
#rocky
[root@localhost ~]# yum -y install postfix
[root@localhost ~]# systemctl enable --now postfix
#ubuntu
[root@ubuntu ~]# apt install mailutils
计划任务的分类
任务类型 | 说明 | 实现程序 |
---|---|---|
一次性任务 | 未来的某时间点执行一次的任务 | at, batch |
周期性任务 | 根据条件周期性执行 | cron |
一次性任务
at 工具
-
由包 at 提供
-
依赖与atd服务,需要启动才能实现at任务
-
at队列存放在/var/spool/at目录中,ubuntu存放在/var/spool/cron/atjobs目录下
-
执行任务时PATH变量的值和当前定义任务的用户身份一致
-
作业执行命令的结果中的标准输出和错误以执行任务的用户身份发邮件通知给 root
-
默认CentOS 8 最小化安装没有安装邮件服务,需要自行安装
at [option] TIME
#常用选项
-V #显示版本信息
-t time #时间格式[[CC]YY]MMDDhhmm[.ss]
-l #列出指定队列中等待运行的作业;相当于atq
-d N #删除指定的N号作业;相当于atrm
-c N #查看具体作业N号任务
-f file #指定的文件中读取任务
-m #当任务被完成之后,将给用户发送邮件,即使没有标准输出
#TIME:定义出什么时候进行 at 这项任务的时间
#HH:MM 在今日的 HH:MM 进行,若该时刻已过,则明天此时执行任务
02:00
#HH:MM YYYY-MM-DD 规定在某年某月的某一天的特殊时刻进行该项任务
02:00 2016-09-20
#HH:MM[am|pm] [Month] [Date]
06pm March 17
17:20 tomorrow
#用具本名词表示时间
noon #正午,中午12点
midnight #午夜,晚上12点
teatime #下午茶时间,下午4点
tomorrow #明天
now #当前时间
#HH:MM[am|pm] + number [minutes|hours|days|weeks], 在某个时间点再加几个时间后才进行该项任务
now + 5 min
02pm + 3 days
at程序的权限控制:
白名单:/etc/at.allow 默认不存在,只有该文件中的用户才能执行at命令
黑名单:/etc/at.deny 默认存在,但内容为空,拒绝该文件中用户执行at命令,而没有在at.deny 文件中的使用者则可执行
如果两个文件都不存在,只有 root 可以执行 at 命令
权限控制是allow的优先级更高,如果用户在allow 和 deny 中都存在,则是有权限执行的
创建at任务有三种方式:交互式创建,输入重定向,at -f FILE
交互式创建
#添加今天0:05的定时任务
[root@ubuntu ~]# at 0:05
warning: commands will be executed using /bin/sh
at Sat May 20 00:05:00 2023
at> touch /tmp/at-00-05
at> echo "at success"
at> <EOT>
job 1 at Sat May 20 00:05:00 2023
#列出任务
[root@ubuntu ~]# at -l
1 Sat May 20 00:05:00 2023 a root
#查看任务具体内容
[root@ubuntu ~]# at -c 1
查看还没有执行的任务
#任务保存在这个目录中
[root@ubuntu ~]# ls -l /var/spool/cron/atjobs/
total 4
-rwx------ 1 root daemon 2947 May 19 22:47 a0000201ac6709
#查看文件,就是上面输入的内容
[root@ubuntu ~]# cat /var/spool/at/a0000201ac6709
到时间查看执行结果
[root@ubuntu ~]# ll /tmp/at-00-05
-rw-r--r-- 1 root root 0 May 20 00:05 /tmp/at-00-05
#输出内容在邮件里面
[root@ubuntu ~]# mail
"/var/mail/root": 1 message 1 new
>N 1 root Sat May 20 00:05 13/422 Output from your job
1
? 1
Return-Path: <root@ubuntu.magedu.org>
X-Original-To: root
Delivered-To: root@ubuntu.magedu.org
Received: by ubuntu.magedu.org (Postfix, from userid 0)
id 0689FA1149; Sat, 20 May 2023 00:05:00 +0800 (CST)
Subject: Output from your job 10
To: root@ubuntu.magedu.org
Message-Id: <20230519160500.0689FA1149@ubuntu.magedu.org>
Date: Sat, 20 May 2023 00:05:00 +0800 (CST)
From: root <root@ubuntu.magedu.org>
at success
#原来生成的任务文件己经被删除了
[root@ubuntu ~]# ls -l /var/spool/cron/atjobs/
total 0
输入输出重定向
#创建
[root@ubuntu ~]# echo reboot | at now+5min
warning: commands will be executed using /bin/sh
job 11 at Sat May 20 00:13:00 2023
#查看
[root@ubuntu ~]# at -l
11 Sat May 20 00:13:00 2023 a root
#删除
[root@ubuntu ~]# at -d 11
[root@ubuntu ~]# at -l
[root@ubuntu ~]#
定时任务一般都是要在将来的某个时间去执行,然后标准输出以及错误输出都不会输出到终端,这是因 为,在任务执行的时候,当前终端没有连接上来,或者不是创建任务的用户;
周期性任务计划 cron
cron 基础知识
-
cron 服务相关程序:
-
cronie:主程序包,提供crond守护进程及相关辅助工具
-
crontabs:包含CentOS提供系统维护任务
-
cronie-anacron:cronie的补充程序,用于监控cronie任务执行状况,如:cronie中的任务在过去该 运行的时间点未能正常运行,则anacron会随后启动一次此任务
cron 依赖于crond服务,确保crond守护处于运行状态:
#CentOS 7 以后版本:
systemctl status crond
#CentOS 6:
service crond status
cron任务分为系统级任务和用户级任务
系统cron任务
操作系统自带的cron 任务,系统维护作业,/etc/crontab 主配置文件, /etc/cron.d/ 子配置文件
用户cron任务
每个用户自己名下的 cron 任务
红帽系统保存在 /var/spool/cron/USERNAME,
Ubuntu 系统存放 在/var/spool/cron/crontabs/USERNAME,利用 crontab 命令管理
cron 程序日志文件
[root@rocky86 ~]# ll /var/log/cron
-rw------- 1 root root 21454 Aug 25 17:01 /var/log/cron
#ubuntu 中的crontab 任务日志放在 /var/log/syslog 中
计划任务时间表示法:
# * 表示该位置上所有可以出现的值
* * * * * #每分钟执行一次
1 2 * * * #每天2时1分执行一次
# , 表示该位置上多个值
1,3,5 2,4,6 * * * #表示第2,4,6 这三个小时中每个小时的第1,3,5 分的时候执行一次
# - 表示范围取值
1-5 2-6 * * * #表示第2到第6小时,第1到第5分每分钟执行一次
# / 表示频率,步长
*/5 */6 * * * #表示每6小时,在该小时内,每5分钟执行一次
# 综合用法
*/5 1,3,5-8 * * 2,4 #每周2和每周4的第1时,第3时,第5到8时,每5分钟执行一次
1 2 1-10 * 1-5 #每月的1到10日,或每周1到周五的2时1分执行一次
1-30/5 * * * * #每小时1-30分内,每5分钟执行一次
#特定关健字
@yearly #每年1月1日执行一次,相当于 0 0 1 1 *
@annually #每年1月1日执行一次,相当于 0 0 1 1 *
@monthly #每月1日执行一次,相当于 0 0 1 * *
@weekly #每周日执行一次,相当于 0 0 * * 0
@daily #每天0时执行一次,相当于 0 0 * * *
@hourly #每小时0分执行一次,相当于 0 * * * *
@reboot #重启后执行一次
系统cron计划任务
系统cron任务是操作系统自己调用的任务,与用户无关
如果想添加系统级的cron任务,写在此文件中
[root@ubuntu ~]# cat /etc/crontab
#系统cron 任务相关文件
/etc/crontab #配置文件
/etc/cron.d/ #配置文件
/etc/cron.hourly/ #脚本
/etc/cron.daily/ #脚本
/etc/cron.weekly/ #脚本
/etc/cron.monthly/ #脚本
用户计划任务
crontab命令:
-
每个用户都有专用的cron任务文件:/var/spool/cron/crontabs/USERNAME
-
默认标准输出和错误会被发邮件给对应的用户,如:mage创建的任务就发送至mage的邮箱 root能够修改其它用户的作业
-
用户的cron中默认 PATH=/usr/bin:/bin,如果使用其它路径,在任务文件的第一行加PATH=/path 或者加入到计划任务执行的脚本中
-
第六个字段指定要运行的命令。 该行的整个命令部分,直至换行符或“%”字符,指定的shell执行, 除非使用反斜杠(\)进行转义,否则该命令中的“%”字符将变为换行符,并且第一个%之后的所有 数据将作为标准输入发送到该命令。
crontab [-u user] [-l | -r | -e] [-i]
#常用选项
-l #列出所有任务
-e #编辑任务
-r #移除所有任务
-i #同-r一同使用,以交互式模式移除指定任务
-u user #管理特定用户的cron, 仅root有权限操作
#查看cron任务
[root@ubuntu ~]# crontab -l
no crontab for root
#root 用户可以查看指定用户的 crontab
[root@ubuntu ~]# crontab -u jose -l
no crontab for jose
修改默认编辑工具
#Ubuntu 首次编辑会提示选择编辑工具
[root@ubuntu ~]# crontab -e
no crontab for root - using an empty one
Select an editor. To change later, run 'select-editor'.
1. /bin/nano <---- easiest
2. /usr/bin/vim.basic
3. /usr/bin/vim.tiny
4. /bin/ed
Choose 1-4 [1]:
#如果没有在此处选择,可以写配置文件修改编辑工具
[root@ubuntu ~]# echo "export EDITOR=vim" >> /etc/profile.d/env.sh
[root@ubuntu ~]# . /etc/profile.d/env.sh
#或者用 select-editor 命令设置默认编辑器
cron中的环境变量
cron中的环境变量和bash 中的环境变量不一致,所以在写 cron 任务时,命令路径要求写全路径,或先 在首部先定义PATH
示例:获取cron中的 PATH 和 BASH
[root@ubuntu ~]# crontab -e
* * * * * /usr/bin/abc "${PATH} ;;; ${BASH};;; ${SHELL}" >>/tmp/cron-test.log
[root@ubuntu ~]# crontab -l
* * * * * echo "$PATH ;;; $BASH" >>/tmp/cron-test.log
#查看日志
[root@ubuntu ~]# tail /tmp/cron-test.log
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/loc
al/games:/snap/bin ;;; ;;; /bin/sh
......
自定义PATH
#方法1,在计划任务配置中指定PATH
[root@rocky86 ~]# crontab -e
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/go/bin
SHELL=/bin/bash
* * * * * echo "${PATH} ;;; ${BASH};;; ${SHELL}" >>/tmp/cron-test.log
#查看日志
[root@ubuntu ~]# tail /tmp/cron-test.log
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/go/bin ;;;
/bin/bash;;; /bin/bash
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/go/bin ;;;
/bin/bash;;; /bin/bash
#方法2,在脚本中指定PATH变量
[root@ubuntu ~]# crontab -l
* * * * * /root/cron-test.sh
#脚本内容
[root@ubuntu ~]# cat cron-test.sh
#!/bin/bash
PATH=/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
echo $PATH >> /tmp/cron-sh-test.log
#查看日志
[root@ubuntu ~]# cat /tmp/cron-sh-test.log
/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
查看不同用户的cron 文件
[root@ubuntu ~]# crontab -l
* * * * * echo "this is test cron from root"
[jose@ubuntu ~]$ crontab -l
* * * * * echo "this is test cron from jose"
[mage@ubuntu ~]$ crontab -l
no crontab for mage
#有cron任务的用户都会有对应的文件
[root@ubuntu ~]# ls -l /var/spool/cron/crontabs/
total 8
-rw------- 1 jose crontab 246 May 20 10:38 jose
-rw------- 1 root crontab 246 May 20 10:38 root
cron 任务中的标准输入输出会发送邮件到用户邮箱
如果不想有邮件,则可以在定时任务中加上重定向
[root@ubuntu ~]# crontab -l
* * * * * echo "this is test cron from root"
* * * * * echo "this is test cron222 from root" &>/dev/null
#查看邮箱
[root@ubuntu ~]# mail
"/var/mail/root": 29 messages 29 unread
>U 1 Cron Daemon Sat May 20 10:41 22/703 Cron <root@ubuntu> echo
"this is test cron from root"
U 2 Cron Daemon Sat May 20 10:42 21/659 Cron <root@ubuntu> echo
"this is test cron from root"
U 3 Cron Daemon Sat May 20 10:43 21/659 Cron <root@ubuntu> echo
"this is test cron from root"
查看执行日志
[root@ubuntu ~]# cat /var/log/syslog
......
......
May 20 11:11:01 ubuntu CRON[3595]: (root) CMD (echo "this is test cron222 from
root" &>/dev/null)
May 20 11:11:01 ubuntu CRON[3597]: (root) CMD (echo "this is test cron from
root")
......
......
交互式删除
[root@ubuntu ~]# crontab -l
* * * * * echo "this is test cron from root"
* * * * * echo "this is test cron222 from root" &>/dev/null
[root@ubuntu ~]# crontab -ir
crontab: really delete root's crontab? (y/n) y
[root@ubuntu ~]# crontab -l
no crontab for root
重定向创建
[root@ubuntu ~]# crontab -l
no crontab for root
[root@ubuntu ~]# echo @reboot echo "this is test msg" | crontab
[root@ubuntu ~]# crontab -l
@reboot echo this is test msg
cron 补充
cron 中 % 的用法
cron任务中不建议使用%,它有特殊用途,它表示换行的特殊意义,且第一个%后的所有字符串会被将 成当作命令的标准输入,如果在命令中要使用%,则需要用 \ 转义
注意:将%放置于单引号中是不支持的
控制用户执行计划任务
/etc/cron.{allow,deny} #ubuntu中无此文件
如何在秒级别运行任务?
用cron 执行脚本,在脚本中写循环还来实现
[root@ubuntu ~]# crontab -l
5 1 * * * /root/cron-test.sh
[root@ubuntu ~]# cat cron-test.sh
#!/bin/bash
PATH=/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/root/bin
for i in {1..60};do
if [ $[$i%5] -eq 0 ];then
echo `date` >> /tmp/cron-sh-test.log
fi
sleep 1
done