进程概念
内核功用: 进程管理, 文件系统, 网络功能, 内存管理, 驱动程序, 安全功能等
Process: 运行中的程序的一个副本, 是被载入内存的一个指令集合
进程 ID(Process ID,PID)号码被用来标记各个进程
UID, GID, 和 SELinux 语境决定对文件系统的存取和访问权限
通常从执行进程的用户来继承
它存在生命周期
task struct:Linux 内核存储进程信息的数据结构格式
task list: 多个任务的的 task struct 组成的链表
进程创建:
init: 第一个进程
进程: 都由其父进程创建, 父子关系, CoW,fork(), clone()
注意:
进程和不是程序, 它是程序加载到内存中之后进行运行的各种指令操作的集合
程序运行时先将它加载到内核空间内存中, 然后再将它分配到用户空间内存中中, 此时相当于系统分配给它一个独立的内存空间. 这时候它便成为了进程, 并且和其他的进程相互隔离. 它认为自己独占了整个内存空间(虚拟出来的内存, 并非真实的内存空间), 并在此基础上进行操作. 实际上它占用的只是系统给它分配的一小块内存空间而已.
进程运行时会随机分配一个进程编号, 运行结束之后会被会被回收. 它运行时就相当于一个资源的集合, 有自己的独立的内存, 能读取数据进去, 有自己的二进制执行程序命令, 包括很多县城等等.
进程内部真正执行操作计算的是线程, 一个线程就是各种指令的集合. 一个进程内至少有一个线程, 可以有多个.
进程的生命周期有长期的(后台进程), 有一次性短期运行的(前台进程). 比如说开机就开始运行的 init 进程, 还有 cat ls 等程序的进程.
task struct : 一个数据结构, 包含了进程的各种元数据.
创建子进程如果用 clone()函数, 就会产生 CoW(写时复制)方式, 类似逻辑卷中的快照: 只有子进程中对数据进行修改了, 才会重新创建一个不同的数据存放于子进程中. 而数据并未更改时它和父进程指向同一个数据, 共用此数据.(最开始学习中的小括号开启子进程, 小括号内局部变量如果不赋值, 仍然和父进程的变量内容一样就是这个原因)
协程就是多个命令的集合代码块(类似函数), 多个协程组成一个线程. 进程中线程的执行顺序的优先级是由操作系统内核来调度的, 而 CPU 在同一时间只能运行一个线程. 我们人看到进程的执行感觉它是同时执行的, 其实它只是利用 CPU 的时间频率分成了多个时间段, 然后一个时间段执行一个线程, 由内核调度, 不论是否完成这个线程, 只要时间段一到, 它就会切换到另一个线程进行运行, 保存当前线程的状态, 这也就是所谓的上下文切换(注意, 线程切换可以是不同进程的线程, 也就相当于切换了不同的进程). 因为 CPU 频率极快, 因此我们看起来它貌似是同步执行了多个进程.
上下文切换会造成 CPU 内的当前线程 (或进程) 缓存数据 (L1,L2,L3) 失效, 相比于 CPU 的运算时间, 这个代价非常巨大, 因此要尽量避免上下文切换进行优化.
进程, 线程和协程
进程相关概念
Page Frame: 页框, 用存储页面数据, 存储 Page 4k (也就是进程使用的内存空间, 类似磁盘的块 block)
物理地址空间和线性地址空间: 物理上的实际内存和应用程序使用时认为的虚拟内存(相当于偏移地址)
MMU:Memory Management Unit 负责转换线性和物理地址, CPU 内的内存管理单元
TLB:Translation Lookaside Buffer 翻译后备缓冲器, 用于保存虚拟地址和物理地址映射关系的缓存
LRU:Least Recently Used : 内存保存数据的算法, 被叫做近期最少使用算法, 用于释放内存, 它的工作原理就是把最新使用的数据存放到内存空间靠前的位置.
比如说一个数据存入内存, 如果内存中已经存在此数据, 则把它的位置提前到内存空间起始位置, 如果没有, 则存入, 并把内存空间终止位置保存的的数据给丢弃(类似堆栈).
用户和内核空间
进程的基本状态和转换
进程的基本状态
创建状态: 进程在创建时需要申请一个空白 PCB(process control block 进程控制块), 向其中填写控制和管理进程的信息, 完成资源分配. 如果创建工作无法完成, 比如资源无法满足, 就无法被调度运行, 把此时进程所处状态称为创建状态
就绪状态: 进程已准备好, 已分配到所需资源, 只要分配到 CPU 就能够立即运行
执行状态: 进程处于就绪状态被调度后, 进程进入执行状态
阻塞状态: 正在执行的进程由于某些事件 (I/O 请求, 申请缓存区失败) 而暂时无法运行, 进程受到阻塞. 在满足请求时进入就绪状态等待系统调用
终止状态: 进程结束, 或出现错误, 或被系统终止, 进入终止状态. 无法再执行
状态之间转换情况
运行 -->就绪: 1, 主要是进程占用 CPU 的时间过长, 而系统分配给该进程占用 CPU 的时间是有限的; 2, 在采用抢先式优先级调度算法的系统中, 当有更高优先级的进程要运行时, 该进程就被迫让出 CPU, 该进程便由执行状态转变为就绪状态
就绪 -->运行: 运行的进程的时间片用完, 调度就转到就绪队列中选择合适的进程分配 CPU
运行 -->阻塞: 正在执行的进程因发生某等待事件而无法执行, 则进程由执行状态变为阻塞状态, 如发生了 I/O 请求
阻塞 -->就绪: 进程所等待的事件已经发生, 就进入就绪队列
以下两种状态是不可能发生的:
阻塞 -->运行: 即使给阻塞进程分配 CPU, 也无法执行, 操作系统在进行调
度时不会从阻塞队列进行挑选, 而是从就绪队列中选取
就绪 -->阻塞: 就绪态根本就没有执行, 谈不上进入阻塞态
IPC 进程间通信
IPC: Inter Process Communication
同一主机:
pipe 管道
socket 套接字文件
signal 信号
shm shared memory
semaphore 信号量, 一种计数器
不同主机:
socket IP 和端口号
RPC remote procedure call
MQ 消息队列, 如: Kafka,RabbitMQ,ActiveMQ
单一主机通讯用 socket 文件, 全双工; 跨网络通讯用 socket 套接字协议.
进程优先级
系统优先级: 数字越小, 优先级越高
0-139: 各有 140 个运行队列和过期队列
实时优先级: 99-0 值最大优先级最高
nice 值:-20 到 19, 对应系统优先级 100-139
Big O: 时间复杂度, 用时和规模的关系
O(1), O(logn), O(n)线性, O(n^2)抛物线, O(2^n)
O(1)比较优先级大小的方式:
通过 140 个编号的优先级队列以及 140 个过时优先级队列, 将优先级编号相同的进程放在对应的优先级栈中 (一个优先级栈可以放多个进程, 从左往右执行), 然后从最小值(最高优先级) 的队列开始执行.
当时间片到而此运行队列中的正在执行的进程没有执行完毕时, 便会保存当前进程状态并将此进程放入相同优先级编号过期队列中, 然后继续执行当前优先级队列中的剩余进程(一个进程在时间片内执行完了就释放, 没有执行完同样放入过期优先级队列中), 直到此队列的所有进程全部执行一遍, 将此队列清空
此时查看此队列相同编号的过时优先级队列, 里面如果有进程, 则将此队列的与过期优先级队列互换身份, 此运行队列变成过期优先级队列, 而过期优先级队列变成正在执行的运行队列. 然后重复 2 中步骤直到此队列的所有进程全部执行完毕并且释放
接下来就是执行下一个最高优先级队列里面的进程了, 重复 1-4 步骤.
进程状态
Linux 内核: 抢占式多任务
进程类型:
守护进程: daemon, 在系统引导过程中启动的进程, 和终端无关进程
前台进程: 跟终端相关, 通过终端启动的进程
注意: 两者可相互转化
进程状态:
运行态: running
就绪态: ready
睡眠态:
可中断: interruptable : 可中断睡眠状态是系统中进程最多的状态
不可中断: uninterruptable
停止态: stopped, 暂停于内存, 但不会被调度, 除非手动启动
僵死态: zombie, 结束进程, 父进程结束前, 子进程不关闭
注意僵死态的进程已经结束了, 但是仍然占用部分资源, kill 命令无法再次关闭它, 最好的方法就是杀掉父进程或者重启系统.
系统管理工具
进程的分类:
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 display a tree of processes
查看进程进程 ps
ps: process state
ps report a snapshot of the current processes : 查看 ps 命令执行时的进程快照
Linux 系统各进程的相关信息均保存在 / proc/PID 目录下的各文件中
ps [OPTION]...
支持三种选项:
UNIX 选项 如 - A -e
BSD 选项 如 a
GNU 选项 如 --help
选项: 不加选项时, 默认显示链接到当前终端中的进程, 无法显示别的终端中进程
a 选项包括链接到所有终端中的进程
x 选项包括不链接终端的进程
u 选项显示进程所有者的信息
f 选项显示进程树, 相当于 --forest
k|--sort 属性 对属性排序, 属性前加 - 表示倒序 : 比如 ps aux k -%CPU , 注意后面的关键字要小写不能大写
o 属性... 选项显示定制的信息 pid, cmd, %CPU, %mem
L 显示支持的属性列表
短格式 (unix) 特有选项
-C cmdlist 指定命令, 多个命令用逗号, 分隔 : 也可以查看脚本, 但要注意用 bash XXX.sh 方式运行的脚本无法查看, 同时如果脚本中没有 #!/bin/bash 就算是直接运行的脚本也无法查看了.
-L 显示线程 : pstree 中花括号内就是线程, 如果没有花括号代表进程只有一个线程(此命令就会显示进程了)
-e: 显示所有进程, 相当于 - A
-f: 显示完整格式程序信息
-F: 显示更完整格式的进程信息
-H: 以进程层级格式显示进程相关信息
-u userlist 指定有效的用户 ID 或名称
-U userlist 指定真正的用户 ID 或名称
-g gid 或 groupname 指定有效的 gid 或组名称
-G gid 或 groupname 指定真正的 gid 或组名称
-p pid 显示指 pid 的进程
--ppid pid 显示属于 pid 的子进程
-M 显示 SELinux 信息, 相当于 Z
注意: 有效用户和真正用户区别, 真正用户是指执行此进程的用户 realuser, 而有效用户代表此进程执行的的权限用户, 比如普通用户执行 passwd 命令, 真正用户为普通用户但有效用户为 root.(组类似)
ps axo pid,cmd,user,ruser,euser , 其中 user 和 euser 相同意义, 代表有效权限用户 ,ruser 代表真正执行用户
ps 输出属性
VSZ: Virtual memory SiZe, 虚拟内存集, 线性内存
进程向操作系统申请的内存, 它的数值可以很大, 但并非全部都使用, 是个虚拟内存, 按照进程自己定义的地址方式来寻址使用
RSS: ReSident Size, 常驻内存集
内核真正分配的内存大小, 常驻内存
STAT: 进程状态
- R:running
- S: interruptable sleeping
- D: uninterruptable sleeping
- T: stopped
- Z: zombie
+: 前台进程
l: 多线程进程
L: 内存分页并带锁
N: 低优先级进程
\<\: 高优先级进程
s: session leader, 会话 (子进程) 发起者
START: 进程启动的时间, 和 date 相关
TIME: 此进程启动后运行所占的时间片累计总时间
PS 中优先级类别
ni(或者 nice): nice 值
pri: priority 优先级
psr: processor CPU 编号
rtprio: 实时优先级
附加知识: renice -n -10(优先级 - 20~19) 8814(PID), 修改进程 nice 优先级
nice -n -5 ping 1.1.1.1 : 直接指定命令的 nice 优先级,(默认为 0 改为 - 5)
附加知识: chrt 修改实时优先级, 不过一般不调整它, 它是系统自动分配设置的, 一般只修改 nice 用户级别的优先级
注意: pri 优先级应该是和前面图中系统优先级刚好相反; 不过有一个特例就是当 realtime 优先级为 0 时, 它也为 0, 而不是 40, 其他的都还符合.
示例:
ps axo pid,cmd,psr,ni,pri,rtprio
常用组合:
- aux
- -ef
- -eFH
- -eo pid,tid,class,rtprio,ni,pri,psr,pcpu,stat,comm
- 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'
进程优先级
进程优先级调整
静态优先级: 100-139
进程默认启动时的 nice 值为 0, 优先级为 120
只有根用户才能降低 nice 值(提高优先性)
nice 命令
nice [OPTION] [COMMAND [ARG]...]
renice 命令
renice [-n] priority pid...
查看
ps axo pid,comm,ni
搜索进程
最灵活方式: ps 选项 | 其它命令
按预定义的模式: pgrep
pgrep [options] pattern
-u uid: effective user, 生效者
-U uid: real user, 真正发起运行命令者
-t terminal: 与指定终端相关的进程
-l: 显示进程名
-a: 显示完整格式的进程名
-P pid: 显示指定进程的子进程
更多详细内容查看帮助即可
按确切的程序名称:/sbin/pidof
pidof bash
注意它和 lsof 区别, lsof 跟的是被打开的文件(或者程序, 因为程序也是文件),pidof 跟的就是进程名(程序如果没运行不是进程)
例子:
- pgrep -lU zhang
- pgrep -aU zhang
- pgrep -P 1
- pgrep -at pts/1
- pgrep -f sshd
- poidof bash
Pidof 更多用法
pidof 进程名 :
通过查看上面命令的 $? 值可以判断进程是否停止运行了, 因此就可以编写脚本监测必须运行的进程, 一旦发现停止立马重新启动(配合计划任务使用极佳, 当然也可以用 killall 0 的方式也可)
例如: 如果 ping 命令没有执行, 则 ping 127.0.0.1, 如果 ping 命令已经执行(不管 ping 的 IP 地址是什么), 则不执行 ping 127.0.0.1
pidof ping &> /dev/null || ping 127.0.0.1
系统工具
/proc/uptime 包括两个值, 单位 s 秒
系统启动时长, 空闲进程的总时长(按总的 CPU 核心数计算)
uptime 和 w
显示当前时间, 系统已启动的时间, 当前上线人数, 系统平均负载(当前时间往前 1, 5, 10 分钟的平均负载, 一般不会超过 1)
系统平均负载:
指在特定时间间隔内运行队列中的平均进程数
通常每个 CPU 内核的当前活动进程数不大于 3, 那么系统的性能良好. 如果每个 CPU 内核的任务数大于 5, 那么此主机的性能有严重问题
如果 Linux 主机是 1 个双核 CPU, 当 Load Average 为 6 的时候说明机器已经被充分使用
进程管理工具
top: 有许多内置命令
排序:
P: 以占据的 CPU 百分比,%CPU
M: 占据内存百分比,%MEM
T: 累积占据 CPU 时长, TIME+
首部信息显示:
uptime 信息: l 命令
tasks 及 CPU 信息: t 命令
CPU 分别显示: 1 (数字)
memory 信息: m 命令
退出命令: q
修改刷新时间间隔: s
终止指定进程: k
保存文件: W
栏位信息简介:
us: 用户空间
sy: 内核空间
ni: 调整 nice 时间
id: 空闲
wa: 等待 IO 时间
hi: 硬中断
si: 软中断(模式切换)
st: 虚拟机偷走的时间(虚拟化技术不成熟时期, 不知道 CPU 的时间片执行了什么进程)
选项:
-d # 指定刷新时间间隔, 默认为 3 秒
-b 全部显示所有进程
-n # 刷新多少次后退出
-H 线程模式, 示例: top -H -p `pidof mysqld`
htop 命令: EPEL 源
选项:
-d #: 指定延迟时间;
-u UserName: 仅显示指定用户的进程
-s COLUME: 以指定字段进行排序
子命令:
s: 跟踪选定进程的系统调用
l: 显示选定进程打开的文件列表
a: 将选定的进程绑定至某指定 CPU 核心
t: 显示进程树
内存空间
内存空间使用状态: free [OPTION]
-b 以字节为单位
-m 以 MB 为单位
-g 以 GB 为单位
-h 易读格式
-o 不显示 -/+buffers/cache 行
-t 显示 RAM + swap 的总和
-s n 刷新间隔为 n 秒
-c n 刷新 n 次后即退出
注意 bufer 和 cache 区别
简单来说一个注重写一个注重读, 不过后期因为有相同的部分它俩区别越来越小
注意磁盘挂载的时候有选项可直接写入硬盘 mount -o sync , 同时 TCP 协议中报头数据 psh 位置也是表示内存是否立即取走.
vmstat 命令: 虚拟内存信息
- vmstat [options] [delay [count]]
- vmstat 2 5
- procs:
r: 可运行 (正运行或等待运行) 进程的个数, 和核心数有关
b: 处于不可中断睡眠态的进程个数(被阻塞的队列的长度), 比如正在读取磁盘文件的进程(IO 接口速度慢, 需要耗费时间)
memory:
swpd: 交换内存的使用总量
free: 空闲物理内存总量
buffer: 用于 buffer 的内存总量
cache: 用于 cache 的内存总量
swap:(注意是相对于内存的进和出来说的, 磁盘进出下同)
si: 从磁盘交换进内存的数据速率(kb/s)
so: 从内存交换至磁盘的数据速率(kb/s)
-io:
bi: 从块设备读入数据到系统的速率(kb/s)
bo: 保存数据至块设备的速率
dd if=/dev/zero of=/dev/null bs=2G : 则 swap 中 so 先涨, 然后 si 再涨
dd if=/dev/sda of=/dev/null : 则 io 中的 bi 涨 ,bo 不变
dd if=/dev/zero of=/dev/sda1/bigfile : 则 io 中的 bi 不变 ,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.
选项:
-s: 显示内存的统计数据
系统监控工具
iostat: 统计 CPU 和设备 IO 信息
示例: iostat 1 10
iftop: 显示带宽使用情况, EPEL 源
示例: iftop -n -i eth1
pmap 命令: 进程对应的内存映射(占用了哪些内存空间, 地址从哪到哪, 以及一些调用的库函数)
pmap [options] pid [...]
-x: 显示详细格式的信息
示例: pmap 1
另外一种实现
cat /proc/PID/maps
用 pmap 来判断内存问题, 看某个程序的内存占用是否一直增长判断它内存泄露
内存泄露: 进程执行完毕不释放所占的内存空间
内存溢出: 进程申请执行时所用的内存空间不够, 直接霸占更多的内存空间进行使用(可能影响其他进程, 如果多霸占的内存空间正好被其他进程使用中)
glances 命令: EPEL 源
glances [-bdehmnrsvyz1] [-B bind] [-c server] [-C conffile] [-p port] [-P password] [--password] [-t refresh] [-f file] [-o output]
内建命令:
- a Sort processes automatically
- c Sort processes by CPU%
- m Sort processes by MEM%
- p Sort processes by name
- i Sort processes by I/O rate
- d Show/hide disk I/O stats
- f Show/hide file system stats
- n Show/hide network stats
- s Show/hide sensors stats
- y Show/hide hddtemp stats
- l Show/hide logs
- b Bytes or bits for network I/O
- w Delete warning logs
- x Delete warning and critical logs
- 1 Global CPU or per-CPU stats
- h Show/hide this help screen
- t View network I/O as combination
- u View cumulative network I/O
- q Quit (Esc and Ctrl-C also work)
常用选项:
-b: 以 Byte 为单位显示网卡数据速率
-d: 关闭磁盘 I/O 模块
-f /path/to/somefile: 设定输入文件位置
-o {HTML|CSV}: 输出格式
-m: 禁用 mount 模块
-n: 禁用网络模块
-t #: 延迟时间间隔
-1: 每个 CPU 的相关数据单独显示
C/S 模式下运行 glances 命令
服务器模式:
glances -s -B IPADDR
IPADDR: 指明监听的本机哪个地址
客户端模式:
glances -c IPADDR
IPADDR: 要连入的服务器端地址
注意两个主机上都要装有 glances 工具, 并且版本要一致(6 和 6,7 和 7), 然后开启服务器的监听功能之后, 客户机就可以随时连接监听服务器端了.
dstat 命令: 系统资源统计, 代替 vmstat,iostat
dstat [-afv] [options..] [delay [count]]
-c 显示 CPU 相关信息
-C #,#,...,total
-d 显示 disk 相关信息
-D total,sda,sdb,...
-g 显示 page 相关统计数据
-m 显示 memory 相关统计数据
-n 显示 network 相关统计数据
-p 显示 process 相关统计数据
-r 显示 io 请求相关的统计数据
-s 显示 swapped 相关的统计数据
- --tcp
- --udp
- --unix
- --raw
- --socket
- --ipc
--top-CPU: 显示最占用 CPU 的进程
--top-io: 显示最占用 io 的进程
--top-mem: 显示最占用内存的进程
--top-latency: 显示延迟最大的进程
iotop
iotop 命令是一个用来监视磁盘 I/O 使用状况的 top 类工具 iotop 具有与 top 相似的 UI, 其中包括 PID, 用户, I/O, 进程等相关信息, 可查看每个进程是如何使用 IO
iotop 输出
第一行: Read 和 Write 速率总计
第二行: 实际的 Read 和 Write 速率
第三行: 参数如下:
线程 ID(按 p 切换为进程 ID)
优先级
用户
磁盘读速率
磁盘写速率
swap 交换百分比
IO 等待所占的百分比
线程 / 进程命令
iotop 常用参数
-o, --only 只显示正在产生 I/O 的进程或线程, 除了传参, 可以在运行过程中按 o 生效
-b, --batch 非交互模式, 一般用来记录日志
-n NUM, --iter=NUM 设置监测的次数, 默认无限. 在非交互模式下很有用
-d SEC, --delay=SEC 设置每次监测的间隔, 默认 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: 改变线程的优先级
nload 查看网络实时吞吐量
nload 是一个实时监控网络流量和带宽使用情况, 以数值和动态图展示进出的流量情况
安装: yum -y install nload (EPEL 源)
界面操作
上下方向键, 左右方向键, enter 键或者 tab 键都就可以切换查看多个网卡的流量情况
按 F2 显示选项窗口
按 q 或者 Ctrl+C 退出 nload
示例:
nload: 默认只查看第一个网络的流量进出情况
nload eth0 eth1: 在 nload 后面指定网卡, 可以指定多个
设置刷新间隔: 默认刷新间隔是 100 毫秒, 可通过 - t 命令设置刷新时间(单位是毫秒)
nload -t 500 eth0
设置单位: 显示两种单位一种是显示 Bit/s, 一种是显示 Byte/s, 默认是以 Bit/s, 也可不显示 / s
-u h|b|k|m|g|H|B|K|M|G 表示的含义: h: auto, b: Bit/s, k: kBit/s, m: MBit/s, H:auto, B: Byte/s, K: kByte/s, M: MByte/s
例子: nload -u M eth0
lsof
lsof:list open files 查看当前系统文件的工具. 在 Linux 环境下, 一切皆文件, 用户通过文件不仅可以访问常规数据, 还可以访问网络连接和硬件如传输控制协议 (TCP) 和用户数据报协议 (UDP) 套接字等, 系统在后台都为该应用程序分配了一个文件描述符
命令参数
-a: 列出打开文件存在的进程
-c < 进程名>: 列出指定进程所打开的文件
-g: 列出 GID 号进程详情
-d < 文件号>: 列出占用该文件号的进程
+d < 目录>: 列出目录下被打开的文件
+D < 目录>: 递归列出目录下被打开的文件
-n < 目录>: 列出使用 NFS 的文件
-i < 条件>: 列出符合条件的进程(4, 6, 协议, : 端口, @ip )
-p < 进程号>: 列出指定进程号所打开的文件
-u: 列出 UID 号进程详情
-h: 显示帮助信息
-v: 显示版本信息.
-n: 不反向解析网络名字
lsof 示例
进程管理
查看由登陆用户启动而非系统启动的进程
lsof /dev/pts/1
指定进程号, 可以查看该进程打开的文件
lsof -p 9527
文件管理
查看指定程序打开的文件
lsof -c httpd
查看指定用户打开的文件
lsof -u root | more
查看指定目录下被打开的文件
- lsof +D /var/log/
- lsof +d /var/log/
参数 + D 为递归列出目录下被打开的文件, 参数 + d 为列出目录下被打开的文件
查看所有网络连接
- lsof -i -n
- lsof [email protected]
通过参数 - i 查看网络连接的情况, 包括连接的 ip, 端口等以及一些服务的连接情况, 例如: sshd 等. 也可以通过指定 ip 查看该 ip 的网络连接情况
查看端口连接情况
lsof -i :80 -n
通过参数 - i: 端口可以查看端口的占用情况,-i 参数还有查看协议, ip 的连接情况等
查看指定进程打开的网络连接
lsof -i -n -a -p 9527
参数 - i, -a, -p 等,-i 查看网络连接情况,-a 查看存在的进程,-p 指定进程
查看指定状态的网络连接
lsof -n -P -i TCP -s TCP:ESTABLISHED
-n:no host names, -P:no port names,-i TCP 指定协议,-s 指定协议状态通过多个参数可以清晰的查看网络连接情况, 协议连接情况等
8. 恢复删除文件(前提是这个删除文件仍然被进程占用着还在内存中)
- lsof |grep /var/log/messages
- rm -f /var/log/messages
lsof |grep /var/log/messages 或者 grep delede : 这一步找到它的进程编号, 下一步进入进程编号文件夹
- cat /proc/653/fd/6
- cat /proc/653/fd/6> /var/log/messages
进程管理工具
kill 命
向进程发送控制信号, 以实现对进程管理, 每个信号对应一个数字, 信号名称以 SIG 开, 头(可省略), 不区分大小写
显示当前系统可用信号: kill -l 或者 trap -l
常用信号: man 7 signal
(1) SIGHUP 无须关闭进程而让其重读配置文件
(2) SIGINT 中止正在运行的进程; 相当于 Ctrl+c 例如 kill -2 `pidof ping`
(3) SIGQUIT 相当于 ctrl+\ :, 有些命令用它退出, 可用 kill -QUIT `pidof bc` 或者 kill -3
(9) SIGKILL 强制杀死正在运行的进程: 强制退出
(15) SIGTERM 终止正在运行的进程: 正常退出
(18) SIGCONT 继续运行
(19) SIGSTOP 后台休眠
指定信号的方法 :
(1) 信号的数字标识: 1, 2, 9
(2) 信号完整名称: SIGHUP
(3) 信号的简写名称: HUP
例子: kill -1
cd /var/www/HTML
echo welcome to my Web>index.HTML
curl 192.168.20.100
VIM /etc/httpd/conf/httpd.conf : 其中的页面文件位置修改为 newhtml
- mkdir newhtml
- cd newhtml
VIM index.HTML : 重新写一个新的页面文件
ps auxf 或者 ps -ef 或者 pidof httpd|apache 或者 pstree -p
kill -1 apache 的父进程 pid(由 root 启动的那个 pid)
kill -n 1 pid : 注意一个带 - 一个不带 -
例子: kill -15 (默认)
ps aux |grep mingetty
kill mingettypid : 此命令执行后发现 pid 号虽然没了, 但是会生成一个新的 pid 号把它重新挂起
pstree -p : 查看是哪一个父进程拉起 mingetty, 发现是 1 进程
kill 1 : 杀不死 1 进程, 但是此时再次执行 kill pidmingetty 发现它无法再自动起来了, 说明此命令对于 1 进程还是有影响的
因此不要随便用 kill 杀进程, 比如杀掉 sshd 服务, 则远程将无法再次连接, 必须在硬件主机上面重启 sshd :systemctl start sshd 才可以再次使用, 这将有可能出现严重问题
按 PID:
- kill [-SIGNAL] pid ...
- kill -n SIGNAL pid
- kill -s SIGNAL pid
按名称: killall [-SIGNAL] comm... : 它可以一次性杀掉对应名字进程包含的所有 pid , 而 kill 一次只能杀掉一个
按模式: pkill [options] pattern (正则表达式)
-SIGNAL :
-u uid: effective user, 生效者
-U uid: real user, 真正发起运行命令者
-t terminal: 与指定终端相关的进程
-l: 显示进程名(pgrep 可用)
-a: 显示完整格式的进程名(pgrep 可用)
-P pid: 显示指定进程的子进程
例子:
pkill -9 -t pts/1 : 把终端上全部进程杀掉包括 bash shell
pkill pin.* : 正则表达式模式法杀掉 ping(或者 pin 开头的任意进程))
killall -0 cmdname 的用法
此命令不进行进程管理, 但是会检查 cmd 名进程是否正常运行, 类似于 pidof , 把返回值存入 $? 中, 用于判断 cmd 进程是否正常运行.
任务作业管理
Linux 的作业控制
前台作业: 通过终端启动, 且启动后一直占据终端
后台作业: 可通过终端启动, 但启动后即转入后台运行(释放终端)
让作业运行于后台
(1) 运行中的作业: Ctrl+z , 它会放入后端但是让它处于 stop 休眠状态
(2) 尚未启动的作业: COMMAND &
注意: 后台作业虽然被送往后台运行, 但其依然与终端相关; 退出当前终端, 将关闭后台作业. 如果希望送往后台后, 剥离与终端的关系, 有以下两种方式:
- nohup COMMAND &> /dev/null &
- screen;COMMAND
查看当前终端所有作业: jobs
作业控制:
fg [[%]JOB_NUM]: 把指定的后台作业调回前台
bg [[%]JOB_NUM]: 让送往后台的作业在后台继续运行
kill [%JOB_NUM]: 终止指定的作业
易混淆点:
killall -18 手动开启休眠状态的进程 ,killall -19 手动停止正在运行的进程. 这两个命令和前端, 后端没有任何关系, 和终端也没有关系, 只要能找到进程, 就可用它操作(也可用 pstree -p 或则 pidof 或者 ps aux 找到进程编号然后 kill -18 -19 也可)
进程和终端相关是因为它是在终端内开了个子 shell 来运行的, 只要终端关闭(比如远程 sshd 服务终端关闭), 父进程都关闭了那么它下面的无论是前端还是后端任务都将会关闭, 例如关闭终端相当于关闭 6681 进程, 则 ping 命令当然会关闭, 无论前端后端.
├─sshd(6994)─┬─sshd(6681)───bash(6683)───ping(6773)
│ └─sshd(129671)───bash(129673)───pstree(6808)
上面都是 centos7 中的逻辑, 但是 centos6 中, 如果终端关闭, 则它下面的子进程会自动挂载到 init 上继续运行, 注意区分.
因此用 nohup 将命令运行之后, 当终端关闭它会挂载到 systemd 上继续运行. 或者还可用 screen 程序, 则终端掉了也不会影响命令的执行.
注意, command & 和 ctrl z 的区别, 一个已经运行调到后端不运行, 一个没有运行调到后端运行.
注意 fg 会把后端的进城调回到前端并运行, 不管它在后端否运行还是不运行. 同样的 bg 也是让进程调回到后端进行运行, 只不过因为进程前段运行的时候无法操作, 同时也没有 jobs 编号, 所以已经运行进程要用 ctrl+z 调到后端停止运行, 然后再用 bg 启动运行.
并行运行
同时运行多个进程, 提高效率(相当于同时启动多个后台程序)
方法 1
- vi all.sh
- f1.sh &
- f2.sh &
- f3.sh &
然后运行此脚本
方法 2
(f1.sh &);(f2.sh &);(f3.sh &)
方法 3: 注意中括号边上有空格
{ f1.sh & f2.sh & f3.sh & }
任务计划
Linux 任务计划, 周期性任务执行
未来的某时间点执行一次任务
at 指定时间点, 执行一次性任务
batch 系统自行选择空闲时间去执行此处指定的任务
周期性运行某任务
cron
at 任务
包: at
at 命令: at [option] TIME
常用选项:
-V 显示版本信息
-t time 时间格式 [[CC]YY]MMDDhhmm[.ss]
-l 列出指定队列中等待运行的作业; 相当于 atq
-d 删除指定的作业; 相当于 atrm
-c #(编号) : 查看具体作业任务
-f /path/file 指定的文件中读取任务
-m 当任务被完成之后, 将给用户发送邮件, 即使没有标准输出
注意: 作业执行命令的结果中的标准输出和错误以邮件通知给相关用户
TIME 格式: 定义出什么时候进行 at 这项任务的时间
- HH:MM [YYYY-mm-dd]
- noon, midnight, teatime(4pm)
- tomorrow
- now+#{
- minutes,hours,days, OR weeks
- }
- HH:MM 02:00
在今日的 HH:MM 进行, 若该时刻已过, 则明天此时执行任务
HH:MM YYYY-MM-DD 02:00 2016-09-20
规定在某年某月的某一天的特殊时刻进行该项任务
- HH:MM[am|pm] [Month] [Date]
- 04pm March 17
- 17:20 tomorrow
- HH:MM[am|pm] + number [minutes|hours|days|weeks]
在某个时间点再加几个时间后才进行该项任务
- now + 5 min
- 02pm + 3 days
注意: 测试中发现如果设置的时间小于当前时间点 (比如现在时间 3 点, 执行命令 2 点) 则它会明天执行 (即使此时把时间改为 1 点 59 分它也不会马上执行了, 因为还有日期的关系, 别忘记了) 需要注意这一点(crontab 中也是这个原理).
执行方式:
(1)交互式 (2)输入重定向 (多行)(3) 管道 | (4)at -f 文件
它依赖于 atd 服务, 需要启动才能实现 at 任务
- rpm -ql at
- systemctl status|start atd.service
at DATE<<EOF : 一行一个任务
- xxx
- xxx
- EOF
- at -l
注意 at 交互式的话需要用 ctrl+d 结束.
at 队列存放在 / var/spool/at 目录中
/etc/at.{allow,deny}控制用户是否能执行 at 任务
白名单:/etc/at.allow 默认不存在, 只有该文件中的用户才能执行 at 命令
黑名单:/etc/at.deny 默认存在, 拒绝该文件中用户执行 at 命令, 而没有在 at.deny 文件中的使用者则可执行
注意点:
如果存在了白名单, 则黑名单无效了, 如果两个文件都不存在, 只有 root 可以执行 at 命令.
直接用 at 命令写的计划任务重启后丢失.
at 中的计划任务命令中的标准输出不会在屏幕上打印, 它会自动写入邮件中发送. 用 - m 可以让没有标准输出的命令也发邮件, 为了证明此 at 任务确实执行了
周期性任务计划 cron
周期性任务计划: cron
相关的程序包:
cronie: 主程序包, 提供 crond 守护进程及相关辅助工具
cronie-anacron:cronie 的补充程序, 用于监控 cronie 任务执行状况, 如 cronie 中的任务在过去该运行的时间点未能正常运行, 则 anacron 会随后启动一次此任务
crontabs: 包含 CentOS 提供系统维护任务
确保 crond 守护处于运行状态:
- CentOS 7:
- systemctl status crond
- CentOS 6:
- service crond status
计划周期性执行的任务提交给 crond, 到指定时间会自动运行系统 cron 任务: 系统维护作业
/etc/crontab : 尽量不要改这个系统级定义的计划任务文件, 而是自己定义, 用命令 crontab -e (参照格式写, 其中 user-name 无需再写)
用户 cron 任务:
crontab 命令
日志:/var/log/cron , 其中记录了计划任务是否执行
注意 rpm -ql cronie 或者 rpn -qf /usr/bin/crontab, 查看信息. 然后 ll /usr/bin/crontab 可以看到它有 suid 权限, 因此用户可以定义计划任务.
系统 cron 任务:/etc/crontab
注释行以 # 开头
详情参见 man 5 crontab
- # Example of job definition:
- # .---------------- minute (0 - 59)
- # | .------------- hour (0 - 23)
- # | | .---------- day of month (1 - 31)
- # | | | .------- month (1 - 12) OR jan,feb,mar,apr ...
- # | | | | .---- day of week (0 - 6) (Sunday=0 or 7) OR sun,mon,tue,wed,thu,fri,sat
- # | | | | |
- # * user-name command to be executed
例如: 晚上 9 点 10 分运行 echo 命令
10 21 * wang /bin/echo "Howdy!"
时间表示法:
(1) 特定值
给定时间点有效取值范围内的值
(2) *
给定时间点上有效取值范围内的所有值
表示 "每..."
(3) 离散取值
#,#,#
(4) 连续取值
#-#
(5) 在指定时间范围上, 定义步长
/#: #即为步长
对应时间格式
@形式 | 时间形式 |
---|---|
@reboot | Run once after reboot |
@yearly | 0 0 1 1 * |
@annually | 0 0 1 1 * |
@monthly | 0 0 1 |
@weekly | 0 0 0 |
@daily | 0 0 * |
@hourly | 0
|
示例: 每 3 小时 echo 和 wall 命令
0 /3 CentOS /bin/echo "howdy"; wall "welcome to Magedu!"
系统的计划任务:
/etc/crontab 配置文件
/etc/cron.d/ 文件夹内的配置文件
/etc/cron.hourly/ 脚本
/etc/cron.daily/ 脚本
/etc/cron.weekly/ 脚本
/etc/cron.monthly/ 脚本
anacron 系统
运行计算机关机时 cron 不运行的任务, CentOS6 以后版本取消 anacron 服务, 由 crond 服务管理
对笔记本电脑, 台式机, 工作站, 偶尔要关机的服务器及其它不一直开机的系统很重要对很有用
配置文件:/etc/anacrontab, 负责执行 / etc/ cron.daily /etc/cron.weekly /etc/cron.monthly 中系统任务
字段 1: 如果在这些日子里没有运行这些任务......
字段 2: 在重新引导后等待这么多分钟后运行它
字段 3: 任务识别器, 在日志文件中标识
字段 4: 要执行的任务
由 / etc/cron.hourly/0anacron 执行
当执行任务时, 更新 / var/spool/anacron/cron.daily 文件的时间戳
管理临时文件
CentOS7 使用 systemd-tmpfiles-setup 服务实现
CentOS6 使用 / etc/cron.daily/tmpwatch 定时清除临时文件
配置文件:
- /etc/tmpfiles.d/.conf
- /run/tmpfiles.d/.conf
- /usr/lib/tmpfiles/*.conf
- /usr/lib/tmpfiles.d/tmp.conf
- d /tmp 1777 root root 10d
- d /var/tmp 1777 root root 30d
主要清除 /tmp (以及 / usr/tmp) 和 /var/tmp 中的文件
命令:
systemd-tmpfiles -clean|remove|create configfile
用户计划任务
crontab 命令定义
每个用户都有专用的 cron 任务文件:/var/spool/cron/USERNAME
crontab 命令:
crontab [-u user] [-l | -r | -e] [-i]
-l 列出所有任务
-e 编辑任务 : 谁执行就是以谁为用户来执行, 因此 user-name 这项不用再写. 同时在执行它的时候会有一个临时文件, 执行完之后便会消除掉它.
-r 移除所有任务
-i 同 - r 一同使用, 以交互式模式移除指定任务
-u user 仅 root 可运行, 指定用户管理 cron 任务
控制用户执行计划任务:
/etc/cron.{allow,deny}
总结 at 和 crontab
一次性作业使用 at
重复性作业使用 crontab
操作 | at 命令 | crontab 命令 |
---|---|---|
Create | at time | crontab -e |
List | at -l | crontab -l |
Details | at -c jobnum | crontab -l |
Remove | at -d jobnum | crontab -r |
Edit | N/A | crontab -e |
没有被重定向的输出会被邮寄给用户
root 能够修改其它用户的作业
注意: 运行结果的标准输出和错误以邮件通知给相关用户
- (1) COMMAND> /dev/null
- (2) COMMAND &> /dev/null
对于 cron 任务来讲,% 有特殊用途; 如果在命令中要使用 %, 则需要转义, 或者将 % 放置于单引号中, 则可不用转义. 如果需要 %(比如 date 命令中), 则要把它写入脚本中, 然后执行脚本即可
注意:
at 和 crontab 在 测试中发现如果设置的时间小于当前时间点 (比如现在时间 3 点, 执行命令 2 点) 则它会明天执行 (即使此时把时间改为 1 点 59 分它也不会马上执行了, 因为还有日期的关系, 别忘记了) 需要注意这一点
写入计划任务的命令的标准输出尽量都扔到垃圾箱里面, 因为它都会以邮件方式进行保存, 如果执行的次数过多也会造成垃圾文件. 所以都重定向到垃圾箱内比较好(当然 at 命令可以不用这样设置, 因为它仅仅执行一次, 甚至用 - m 强行发送邮件判断它是否执行)
脚本或者命令最好写全路径.
注意一点, 如果时间格式如下所示, 则代表的日子和星期并非是与的关系, 而是或的关系, 它表示每月的 1 10 20 日和每周的星期 1 5 都会进行计划任务.
如果非要是与的关系, 则只能在后面的 CMD 中进行判断了, 比如下面的判断是否是周日
- 30 23 1,10,20 * 1,5 CMD
- 30 23 1,10,20 * * [ `date +%w` -eq 0 ] && cmd
例子: 计划任务来重启 httpd 服务
- cat /etc/crontab
- crontab -e
- * * * * */usr/bin/killall -0 httpd &> /dev/null || systemctl start httpd
- crontab -l
- cat /var/spool/cron/root
- cat /var/log/cron
思考:
(1) 如何在秒级别运行任务?
for min in 0 1 2; do echo "hi"; sleep 20; done
(2) 如何实现每 7 分钟运行一次任务?
sleep 命令:
- sleep NUMBER[SUFFIX]...
- SUFFIX:
s: 秒, 默认
m: 分
h: 小时
d: 天
usleep: 标准单位为 1us, 微秒
usleep 1000000 : 此为 1 秒
来源: http://www.bubuko.com/infodetail-3015590.html