1 进程和内存管理
内核功能:
进程管理
内存管理
文件系统管理
网络管理
驱动程序管理
安全管理
...
单核CPU如何同时处理多个进程?
CPU的计算速度是非常快的, 利用这个特点, 把CPU工作时间, 切分成多个小的时间片, 这就是CPU分片
分片后的单位时间是无法被人类感知的, 这样就可以在不同的时间片, 运行不同的任务, 让CPU在不同的进程上切换运行, 任务运行的短暂停留无法被人类感知, 所以给人的感觉就像程序一直在运行一样
为了避免某个进程/任务, 始终占据着CPU, 内核会进行CPU的调度, 让其在不同的进程上运行, 处理不同的进程
1.1 什么是进程
进程: 运行中的程序的一个副本, 是被载入内存的一个指令集合, 是资源分配的单位
进程ID(PID)号码被用来标记各个进程
进程运行身份UID, GID,和SELinux语境决定对文件系统的存取和访问权限
运行身份通常从执行进程的用户来继承
进程存在生命周期
同一个进程, 被不同的用户启动时, 会产生多实例, 不同用户运行的进程是独立的
进程创建:
init: 操作系统第一个进程, 从CentOS7后改为systemd
进程都由其父进程创建, 利用fork()系统调用, 采用 CoW: Copy On Write,写实复制机制
进程被加载到内存后, 由cpu负责运行
[root@c6 ~]# pstree -p
init(1)─┬─auditd(1204)───{auditd}(1205)
├─crond(1474)
├─master(1460)─┬─pickup(1466)
│ └─qmgr(1467)
[23:03:04 root@CentOS-7-1 ~]#pstree -p
systemd(1)─┬─NetworkManager(542)─┬─{NetworkManager}(560)
│ └─{NetworkManager}(563)
├─VGAuthService(531)
├─agetty(556)
├─auditd(509)───{auditd}(510)
[23:00:11 root@CentOS-8-1 ~]#pstree -p # 用花括号括起来的是线程
systemd(1)─┬─NetworkManager(717)─┬─{NetworkManager}(755)
│ └─{NetworkManager}(761)
进程, 线程和携程
- 进程: 运行中的程序的一个副本, 是被载入内存的一个指令集合, 是资源分配的单位
执行一个命令, 其磁盘文件会被加载到内存, 启动为进程
进程是资源分配的单位, 包括代码, 访问的文件, 数据, 占用的地址空间, 线程和携程信息
进程包含程序代码
进程也可以查看或者编辑其他的文件, 这就需要把进程访问的文件也加载到内存, cat /etc/issue
线程: 隶属于进程的一部分, 一个进程至少有一个线程, 多个线程间共享其进程资源, 因此会产生资源冲突, 一个线程出现故障, 有可能会影响其他线程. 而进程间是独立的, 不会互相影响
进程和线程的调度是靠内核管理的, 为了提高CPU的运行效率, 可以让多进程或多线程并行运行
单线程和多线程
[23:03:04 root@CentOS-7-1 ~]#pstree -p
systemd(1)─┬─NetworkManager(542)─┬─{NetworkManager}(560) # 多线程
│ └─{NetworkManager}(563)
├─VGAuthService(531) # 单线程
查看进程中的线程
- 线程信息可以通过/proc目录下, 对应的PID目录中的status文件查看
[16:50:42 root@centos-7-1 ~]#ls /proc
1 13 2 235 250 281 31 424 434 443 513 553 9 bus dma ioports kpageflags mpt self timer_list
10 132 20 238 255 282 32 425 435 45 537 6 95 cgroups driver irq loadavg mtrr slabinfo timer_stats
1061 14 21 24 256 283 33 428 438 460 541 60 961 cmdline execdomains kallsyms locks net softirqs tty
1063 15 22 240 276 284 365 429 439 462 544 7 967 consoles fb kcore mdstat pagetypeinfo stat uptime
1064 16 23 245 277 285 387 43 44 463 545 8 968 cpuinfo filesystems keys meminfo partitions swaps version
1068 17 232 246 278 286 4 430 440 465 546 806 acpi crypto fs key-users misc sched_debug sys vmallocinfo
1087 18 233 248 279 287 41 431 441 47 547 807 asound devices interrupts kmsg modules schedstat sysrq-trigger vmstat
11 19 234 249 280 30 423 432 442 5 548 810 buddyinfo diskstats iomem kpagecount mounts scsi sysvipc zoneinfo
[16:51:00 root@centos-7-1 ~]#cat /proc/1061/status | grep -i thread
Threads: 1 # 1表示单线程, 大于1表示多线程
Speculation_Store_Bypass: thread vulnerable
如果判断一个进程是单线程还是多线程?
#1. pstree -p: 带花括号括起来的就是多线程
#2. cat /proc/1061/status | grep -i thread: Threads值为1是单线程, 大于1是多线程
#3. ps aux: stat带有l标识, 表示多线程
1.2 进程结构
内核把进程放在叫做任务队列(task list)的双向循环链表中
链表中的每一项都是类型为task_struct, 称为进程控制块(Processing Control Block), PCB中包含一个具体进程的所有信息
进程控制块PCB包含信息:
进程id、用户id和组id
程序计数器
进程的状态(有就绪、运行、阻塞)
进程切换时需要保存和恢复的CPU寄存器的值
描述虚拟地址空间的信息
描述控制终端的信息
当前工作目录
文件描述符表,包含很多指向file结构体的指针
进程可以使用的资源上限(ulimit –a命令可以查看)
输入输出状态:配置进程使用I/O设备
1.3 进程相关概念
1.3.1 存储单位
Page Frame: 页框, 用于存储页面数据, 一个Page为4k
[17:28:42 root@centos-7-1 ~]#getconf -a | grep -i size
PAGESIZE 4096
PAGE_SIZE 4096
...
1.3.2 物理地址空间和虚拟地址空间
物理地址空间: 操作系统实际给进程分配的地址空间
虚拟地址空间: 进程认为自己独占整个操作系统空间, 这样进程在运行时就不会互相干扰
MMU: Memory Management Unit 负责虚拟地址转换为物理地址
程序在访问一个内存地址指向的内存时, CPU不是直接把这个地址送到内存总线上, 而是被送到MMU, 然后把这个内存地址映射到实际的物理内存地址上, 然后通过总线再去访问内存, 程序操作的地址称为虚拟内存地址
TLB: Transaction Lookaside Buffer, 后备缓冲器, 用于保存虚拟地址和物理地址映射关系的缓存. 之后再进行虚拟内存到物理内存的映射时, 就可以直接从缓存中获取数据
1.3.3 用户空间和内核空间
操作系统的内存空间分为用户空间(进程)和内核空间(内核)
每个进程认为自己独占整个用户空间
用户空间存放了进程的代码段, 数据, BSS, 以及堆栈信息
1.3.4 c代码和内存布局之间的对应关系
每个进程都包括5中不同的数据段
- 代码段: 用来存放可执行文件的操作指令, 也就是说它是可执行程序在内存中的镜像. 代码段需要防止在运行时被非法修改, 所以只准许读取操作, 而不允许写操作 -- 也就是代码段是不可写的
- 数据段: 用来存放可执行文件中已初始化的全局变量, 也就是存放程序静态分配的变量和全局变量
- BSS段: Block Started by Symbol, 以符号开始的块, BSS段包含了程中未初始化的全局变量, 在内存中BSS段全部置位0
- 堆(heap): 存放数组和对象, 堆是用于存放进程进行中被动态分配的内存段, 它的大小不固定, 可以扩张也可以缩减. 当进程调用malloc的函数分配内存时, 新分配的内存就被动态添加到堆上; 当利用free等函数释放内存时, 被释放的内存从堆中被剔除(堆被缩减). 堆的数据可以动态存取, 没有后进先出, 或者先进先出的特点
- 栈: 栈是用户存放程序临时创建的局部变量, 也就是函数{}中定义的变量, 但不包括static声明的变量, static意味着在数据段中存放变量. 除此之外, 在函数被调用时, 其参数也会被压入发起调用的进程栈中, 并且待到调用结束后, 函数的返回值也会被存放回栈中. 由于栈区的后进先出特点, 所以栈区特别方便用来恢复/保存调用现场. 可以把堆栈看成一个寄存、交换临时数据的内存区域
1.3.5 进程使用内存的问题
1.3.5.1 内存泄漏: Memory Leak
忘删了
指程序中用malloc或new申请了一块内存, 但是用完后, 没有用free或delete将内存释放, 导致这块内存一直处于占用状态
1.3.5.2 内存溢出: Memory Overflow
写多了
指程序中申请了固定的空间, 比如10M, 但是在这个空间写入了超过10M字节的数据, 这就是内存溢出
1.3.5.3 内存不足: OOM
没多余的了
Out of Memory, 一般在Java程勋中比较常见. 系统会选择一个进程将之杀死, 在日志中会看到Out of Memory信息
当JVM因为没有足够的内存来为对象分配空间并且垃圾回收器也已经没有空间可回收时, 就会抛出OOM, 因为该问题已经严重到不能被应用处理
Jul 10 10:20:30 kernel: Out of memory: Kill process 9527 (java) score 88 or sacrifice child
OOM原因:
给应用分配的内存太少
应用程序使用内存过多, 并且没有及时释放, 此时就会造成内存泄漏或者内存溢出
解决方案:
1. 限制Java进程能使用的最大的堆区(数据)空间, 并且降低Java程序的worker数量, 从而降低内存使用
2. 给系统增加Swap空间
3. 设置内存参数, 不允许内存申请过量
echo 2 > /proc/sys/vm/overcommit_memory
echo 80 > /proc/sys/vm/overcommit_ratio
echo 2 > /proc/sys/vm/panic_on_oom
不过不推荐设置内核参数干预内存使用
内核参数的调整并不是最好的方案, 当出现内存问题时, 最好是要分析出问题的根源, 之后予以整改
内核参数调整:
Linux默认允许memory overcommit, 只要应用程序申请内存, 就会予以分配, 一旦内存超出, 会通过OOM Killer机制
挑选出一个进程杀死, 来释放空间, 如果内存空间还是不足, 就继续杀死进程
也可以通过设置内核参数 vm.panic_on_oom 使得发生OOM时自动重启系统.
但是, 无论是杀死进程还是重启系统都会造成业务中断, 所以当出现内存问题时, 最好是要分析出问题的根源, 之后予以整改
- vm.panic_on_oom: 决定系统出现OOM的时候, 要做的操作
0 - 默认值, 当出现OOM时, 触发OOM Killer杀死进程
1 - 程序在有cpuset, memory policy, memcg的约束情况下的OOM, 可以考虑不panic, 而是启动OOM Killer. 其他情况触发了 kernel panic, 那么系统直接重启
2 - 当出现OOM, 直接触发kernel panic, 系统直接重启
- Linux内核2.6之后, 允许通过内核参数 vm.overcommit_memory 来禁止memory overcommit
0 - Heuristic overcommit Handling, 默认值, 允许overcommit, 但是明目张胆的overcommit会被拒绝, 比如malloc一次性申请的内存大小超过了系统总内存. Heuristic的意思是试探式的, 内核利用某种算法猜测内存申请是否合理, 如果认为不合理就拒绝overcommit
1 - Always overcommit, 允许overcommit, 对内存申请都允许. 内核执行无内存过量使用处理. 使用这个设置会增大内存超载的可能性, 但也可以增强大量使用内存任务的性能
2 - Don't overcommit, 禁止overcommit. 内核拒绝等于或者大于总可用swap空间大小以及overcommit_ratio指定的物理RAM比例的内存请求. 如果希望减小内存过度使用的风险, 这个参数是最好的
- 内核设有一个阈值, 申请的内存总数超过这个阈值就算overcommit, 在/proc/meminfo中可以看到
[19:03:28 root@centos-7-1 ~]#grep -i commit /proc/meminfo
CommitLimit: 2594988 kB
Committed_AS: 216008 kB
CommitLimit 就是overcommit的阈值, 申请的内存总数超过CommitLimit的数值就被认为overcommit
此值是通过内核参数vm.overcommit_ratio或vm.overcommit_kbytes间接设置的
- vm.overcommit_ratio是内核参数, 默认为50, 表示物理内存的50%. 如果不想用此比例, 也可以直接指定内存的字节数大小, 通过另一个内核参数vm.overcommit_kbytes指定
/proc/meminfo中的Committed_AS表示所有进程已经申请的内存总大小, 是已经申请了的, 而非已经分配的.
如果Commited_AS超过了CommitLimit就表示发生了overcommit, 超出越多表示overcommit越严重
Committed_AS代表了如果要保证不发生OOM, 那么Committed_AS不能超过CommittedLimit的大小
[23:13:29 root@CentOS-7-1 ~]#cat /proc/sys/vm/panic_on_oom
0
[23:44:14 root@CentOS-7-1 ~]#cat /proc/sys/vm/overcommit_memory
0
[23:44:20 root@CentOS-7-1 ~]#cat /proc/sys/vm/overcommit_ratio
50
[23:44:24 root@CentOS-7-1 ~]#grep -i commit /proc/meminfo
CommitLimit: 2594988 kB
Committed_AS: 215900 kB
1.4 进程状态
进程的基本状态
创建状态: 进程在创建时需要申请一个空白PCB, 向其中填写控制和管理进程的信息, 完成资源分配. 如果创建工作无法完成, 比如资源无法满足, 就无法被调度运行, 把此时进程所处状态称为创建状态
就绪状态: 进程已经准备好, 已分配到所需资源, 只要分配的CPU就能够立即运行
执行状态: 进程处于就绪状态被调度后, 进程进入执行状态
阻塞状态: 正在被执行的进程, 由于某些事件(I/O请求, 申请缓存区失败)而暂时无法运行, 进程受到阻塞. 在满足请求时进入就绪状态等待系统调用
终止状态: 进程结束, 或出现错误, 或被系统终止, 进入终止状态, 无法再执行
进程更多的状态
运行态: running
就绪态: ready
睡眠态: 分为两种, 可中断睡眠(睡眠状态可以被中断, 转为其他状态); interruptable, 不可中断睡眠(无法干预, 达到一定状态会自动唤醒); uninterruptable
停止态: stopped, 暂停于内存, 但不会被调度, 除非手动启动
僵尸态(Z): zombie, 僵尸态, 结束的进程, 进程运行完,但是没有父进程将其关闭,或者子进程运行完, 父进程还没有运行结束. 可以直接杀死父进程或者恢复父进程都可以关闭僵尸态的子进程
进程间的转换
运行 --> 就绪:
1. 程序进程需要占用CPU的时间过长, 而系统分配给进程占用CPU的时间是有限的, 进程就会在运行和就绪态间切换
2. 在采用抢占式优先级调度算法的系统中, 当有更高优先级的进程要运行时, 该进程就被迫让出CPU, 该进程便由执行状态转变为就绪状态
就绪 --> 运行:
运行的进程的时间片用完, 调度就转到就绪队列中选择合适的进程分配CPU
运行 --> 阻塞:
正在执行的进程因发生某等待事件而无法执行, 则进程由执行状态变成阻塞状态, 如发生了I/O请求
阻塞 --> 就绪:
进程所等待的事件已经发生, 就进入就绪队里
- 以下两种状态是不可能发生的
阻塞 --> 运行:
即使给阻塞进程分配CPU, 也无法执行, 操作系统在进行调度时不会从阻塞队列进行挑选, 而是从就绪队列中选取
就绪 --> 阻塞:
就绪态根本没有执行, 也就谈不上阻塞态
一台服务器, 正常情况下, 最多的状态是睡眠态. 虽然CPU可以是多核, 并且进行分片, 但是同一个CPU时间点, 还是只能运行CPU相同核数的进程, 所以一台服务器最多的进程状态不是运行态.
而对于就绪态指的是已经分配到了资源, 就等着拿到CPU资源去运行. 但是实际服务器上并不会有大量的进程已经拿到资源, 正在等待CPU去执行
范例: 关闭僵尸进程
先构建僵尸进程
[12:17:46 root@CentOS-8-1 ~]#echo $BASHPID # 父进程
1364
[12:18:35 root@CentOS-8-1 ~]#bash # 开启子进程
[12:18:39 root@CentOS-8-1 ~]#echo $BASHPID, $PPID
1385, 1364
9 --> SIGKILL 强制杀死正在运行的进程
15 --> SIGTERM 终止正在运行的进程, 默认信号
18 --> SIGCONT 继续运行
19 --> SIGSTOP 后台休眠, 变成T状态
[12:18:50 root@CentOS-8-1 ~]#kill -19 1364 # 停止父进程
[12:20:30 root@CentOS-8-1 ~]#kill -9 1385 # 杀死子进程
方法1: 恢复父进程
[12:20:51 root@CentOS-8-1 ~]#kill -18 1364
方法2: 直接杀死父进程
[12:25:02 root@CentOS-8-1 ~]#echo $BASHPID
1364
[12:25:06 root@CentOS-8-1 ~]#bash
[12:25:11 root@CentOS-8-1 ~]#echo $BASHPID, $PPID
1429, 1364
[12:25:18 root@CentOS-8-1 ~]#kill -19 1364 # 停止父进程
[12:26:08 root@CentOS-8-1 ~]#kill -9 1429 # 杀死子进程
[12:28:02 root@CentOS-8-1 ~]#kill -9 1364
1.5 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
可以利用缓存技术, 将硬盘中的数据放入内存, 来加快访问速度; 但是, 内存的空间是有限的, 就需要相应的算法来控制数据在内存中的存储情况 - LRU
近期被访问的数据会按照先进先出的原则, 存入内存, 如果某段时间内, 某个数据被访问的次数最少, 就会从内存删除, 而内存只保留被频繁访问的数据
1.6 IPC 进程间通信
IPC: Inter Process Communication
- 同一主机
pipe 管道, 单向传输, 数据被读取后就会删除
socket 套接字文件, 双向传输
Memory-mapped file 文件映射, 将文件中的一段数据映射到物理内存, 多个进程共享这片内存
shm shared memory 共享内存
signal 信号
Lock 对资源上锁, 如果资源已被某个进程锁住, 则其他进程想修改甚至读取这些资源, 都将被阻塞, 直至锁被打开
smeaphore 信号量, 一种计数器
- 不同主机: socket=IP和端口号
RPC: Remote Procedure Call
MQ: 消息队列, 生产者和消费者, 如, Kafka, RabbitMQ, ActiveMQ
- socket
同一主机: 套接字文件
不同主机: IP:PORT
1.7 进程优先级
CentOS优先级
不同的优先级都遵循从右到左, 优先级递增; 非系统进程一般属于右侧的优先级划分
系统优先级: 0-139, 数字越小, 优先级越高, 各有140个运行队里和过期队列
系统优先级又被分成实时优先级和nice优先级
实时优先级: 99-0, 值越大优先级越高
nice值: -20到19, 对应系统优先级100-139
默认情况每个进程的系统优先级为120, 对应nice优先级0
1.8 进程分类
操作系统分类:
协作式多任务:早期 Windows 系统使用,即当一个任务得到了 CPU 时间,除非它自己放弃使用CPU ,否则将完全霸占 CPU ,所以任务之间需要协作——使用一段时间的 CPU ,主动放弃使用
抢占式多任务:Linux内核,CPU的总控制权在操作系统手中,操作系统会轮流询问每一个任务是否需要使用 CPU ,需要使用的话就让它用,不过在一定时间后,操作系统会剥夺当前任务的 CPU 使用权,把它排在询问队列的最后,再去询问下一个任务
进程类型:
- 守护进程: daemon, 在系统引导过程中启动的进程,开机就会运行, 和终端无关
- 前台进程:跟终端相关,通过终端启动的进程
注意:两者可相互转化
按进程资源使用的分类:
- CPU-Bound:CPU密集型,非交互
- IO-Bound:IO密集型,交互
2 进程管理和性能相关工具
Linux系统的状态的查看及管理工具: pstree, ps, pidof, pgrep, top, htop, glance, pmap, vmstat, dstat, kill, pkill, job, bg, fg, nohup
2.1 进程树 pstree
pstree, 树形结构显示进程的父子关系, 常用pstree, pstree -p(显示PID)
案例: 显示以某个用户身份运行的程序
21:20:23 root@centos-7-1 ~]#pstree postfix
pickup
qmgr
2.2 进程信息ps
查看进行状态, 默认显示当前终端中的进程, Linux系统各进程的相关信息均保存在/proc/PID目录下的各文件中
[19:59:40 root@centos-7-1 ~]#ps aux
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 2 0.0 0.0 0 0 ? S 16:35 0:00 [kthreadd]
USER: 进程由哪个用户运行
PID: 该进程的PID
%CPU: 进程所占用的CPU百分比
%MEM: 进程所占用内存的百分比
VSZ: 进程被分配的虚拟内存
RSS: 进程实际使用的物理内存
TTY: 进程运行终端信息
STAT: 进程状态信息
START: 进程启动时间
TIME: 进程运行的时间
COMMAND: 进程运行的命令
进程的STAT状态:
R: running, 运行态
S: interruptable sleeping, 可中断睡眠
D: uninterruptable sleeping, 不可中断睡眠
T: stopped
Z: zombie
+: 前台进程
l: 多线程进程
L: 内存分页并带锁
N: 低优先级进程
<: 高优先级进程
s: session leader, 会话(子进程)发起者
I: idle kernel thread, CentOS 8新特性
常用组合
ps aux: 显示信息更全面
ps -ef
ps axo pid,cmd,psr,ni,pri,rtprio # 查看进程的特定属性
ni: nice值
pri: priority优先级
rtprio: 实时优先级
psr: processor CPU编号
常用选项
a 选项包括所有终端中的进程
x 选项包括不链接终端的进程
u 选项显示进程所有者的信息
f 选项显示进程树,相当于 --forest
k|--sort 属性 对属性排序,属性前加 - 表示倒序
o 属性… 选项显示定制的信息 pid、cmd、%cpu、%mem
L 显示支持的属性列表
-C cmdlist 指定命令,多个命令用,分隔
-L 显示线程
-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的子进程
-t ttylist 指定tty,相当于 t
-M 显示SELinux信息,相当于Z
# 选项间不能有空格
[20:10:27 root@centos-7-1 ~]#ps axo pid,cmd,psr,ni,pri,rtprio
PID CMD PSR NI PRI RTPRIO
1 /usr/lib/systemd/systemd -- 0 0 19 -
2 [kthreadd] 0 0 19 -
4 [kworker/0:0H] 0 -20 39 -
6 [ksoftirqd/0] 0 0 19 -
7 [migration/0] 0 - 139 99
案例: 构建僵尸态, 并处理
一般僵尸态的进程已经运行结束, 不会占用太多资源, 一般不需要处理
9 --> SIGKILL 强制杀死正在运行的进程
15 --> SIGTERM 终止正在运行的进程, 默认信号
18 --> SIGCONT 继续运行
19 --> SIGSTOP 后台休眠
1. 执行bash, 开启子进程
─sshd(807)───sshd(1064)───bash(1068)───bash(26492)───pstree(26505)
# 此时, 26492的父进程为1608
2. 将父进程设为停止态
kill -19 1068
[20:21:07 root@centos-7-1 ~]#ps aux | grep 1068
root 1068 0.0 0.2 116048 2684 pts/0 Ts 16:50 0:00 -bash # T: 停止态
3. 查看此时的父子进程状态
[20:21:15 root@centos-7-1 ~]#ps auxf # f参数可查看父子进程关系
root 1068 0.0 0.2 116048 2684 pts/0 Ts 16:50 0:00 \_ -bash # 此时父进程处于T, 停止态
root 26492 0.0 0.2 115940 2480 pts/0 S 20:19 0:00 \_ bash # 此时子进程处于可中断睡眠
root 26508 0.0 0.1 155608 1948 pts/0 R+ 20:22 0:00 \_ ps auxf
4. kill子进程
[20:22:10 root@centos-7-1 ~]#kill -9 26492
5. 切换到另一个终端, 查看进程状态
[20:25:45 root@centos-7-1 ~]#ps auxf
root 1068 0.0 0.2 116048 2684 pts/0 Ts 16:50 0:00 | \_ -bash
root 26492 0.0 0.0 0 0 pts/0 Z+ 20:19 0:00 | \_ [bash] <defunct> # 子进程处于Z状态, 同时可以看到vss和rss都为0,因此僵尸态本身并不太消耗内存空间
6. 将父进程恢复, 即可关闭僵尸态子进程
恢复父进程后, 子进程的僵尸态会变为killed, 也就是被关闭
[20:31:08 root@centos-7-1 ~]#kill -18 1068
7. 或者直接杀死父进程
kill -9 父进程PID
案例: 查看指定属性
ps axo o 选项可以用来查看指定的属性
[21:21:46 root@centos-7-1 ~]#ps axo pid,cmd,pri,ni
PID CMD PRI NI
1 /usr/lib/systemd/systemd -- 19 0
案例: 查看指定的属性, 并按照指定列正序排序
[21:21:51 root@centos-7-1 ~]#ps axo pid,cmd,ni,pri,%cpu,%mem k %cpu
PID CMD NI PRI %CPU %MEM
1 /usr/lib/systemd/systemd -- 0 19 0.0 0.3
2 [kthreadd] 0 19 0.0 0.0
案例: 查看指定的属性, 并按照指定列倒序排序
[21:23:17 root@centos-7-1 ~]#ps axo pid,cmd,ni,pri,%cpu,%mem k -%cpu
PID CMD NI PRI %CPU %MEM
546 /usr/bin/vmtoolsd 0 19 0.2 0.6
26532 [kworker/0:2] 0 19 0.1 0.0
案例: --sort 参数也可以实现排序
正序:
[21:24:40 root@centos-7-1 ~]#ps axo pid,cmd,ni,pri,%cpu,%mem --sort %cpu
倒序:
[21:24:40 root@centos-7-1 ~]#ps axo pid,cmd,ni,pri,%cpu,%mem --sort -%cpu
案例: 按照父子进程关系显示
[14:03:42 root@CentOS-8-1 ~]#ps auxf | grep bash
root 1405 0.0 0.5 26144 4760 pts/1 Ss 12:20 0:00 | \_ -bash
root 1452 0.0 0.5 26144 4588 pts/0 Ss 12:27 0:00 \_ -bash
root 1583 0.0 0.5 26128 4780 pts/0 S 14:03 0:00 \_ bash
root 1600 0.0 0.5 26128 4776 pts/0 S 14:03 0:00 \_ bash
root 1617 0.0 0.5 26128 4788 pts/0 S 14:03 0:00 \_ bash
root 1636 0.0 0.1 12108 1068 pts/0 S+ 14:04 0:00 \_ grep --color=auto bash
2.3 查看进程信息 prtstat
来自prmisc包
显示内容更全
[21:26:11 root@centos-7-1 ~]#prtstat 26512
Process: bash State: S (sleeping)
CPU#: 0 TTY: 136:1 Threads: 1
Process, Group and Session IDs
Process ID: 26512 Parent ID: 26510
Group ID: 26512 Session ID: 26512
T Group ID: 28588
Page Faults
This Process (minor major): 2643 0
Child Processes (minor major): 14568 0
CPU Times
This Process (user system guest blkio): 0.10 0.03 0.00 0.00
Child processes (user system guest): 0.12 0.89 0.00
Memory
Vsize: 118 MB
RSS: 2527 kB RSS Limit: 18446744073709 MB
Code Start: 0x400000 Code Stop: 0x4dd524
Stack Start: 0x7fff03ef8ba0
Stack Pointer (ESP): 0x7fff03ef8658 Inst Pointer (EIP): 0x7f454165446c
Scheduling
Policy: normal
Nice: 0 RT Priority: 0 (non RT)
2.4 设置和调整优先级
进程优先级调整
只有静态优先级可以手动调整: 100-139
进程默认启动时的nice值为0, 对应系统优先级为120
只有root用户才能降低nice值, 来提高进程的优先级
nice命令
以指定的优先级来启动进程
nice [OPTION] [COMMAND [ARG]...]
-n, --adjustment=N add integer N to the niceness (default 10)
renice命令
可以调整正在执行中的进程的优先级
renice [-n] priority pid...
查看nice优先级
[14:12:44 root@CentOS-8-1 ~]#ps axo pid,cmd,ni
PID CMD NI
1 /usr/lib/systemd/systemd -- 0
2 [kthreadd] 0
3 [rcu_gp] -20
4 [rcu_par_gp] -20
5 [kworker/0:0-events] 0
6 [kworker/0:0H-kblockd] -20
8 [mm_percpu_wq] -20
9 [ksoftirqd/0] 0
10 [rcu_sched] 0
11 [migration/0] -
12 [watchdog/0] -
13 [cpuhp/0] 0
案例: 手动提高nice优先级
# 以指定的nice优先级启动进程
[14:15:16 root@CentOS-7-1 ~]#nice -n -1 ping 127.0.0.1
[14:13:58 root@CentOS-7-1 ~]#ps axo pid,comm,ni
...
26297 ping -1
26298 sshd 0
26300 bash 0
26319 ps 0
运行中的进程也可以修改其nice优先级, 方法和上述手动方法一致(换成renice命令即可)
[14:14:09 root@CentOS-7-1 ~]#renice -n -20 26297
26297 (process ID) old priority -1, new priority -20
[14:14:26 root@CentOS-7-1 ~]#ps axo pid,comm,ni
...
26297 ping -20
26298 sshd 0
26300 bash 0
26321 ps 0
提升了优先级也不会保证进程优先执行, 还要看内核调度和进程的运行情况
2.5 搜索进程
ps选项 | grep "pattern" 灵活
2.5.1 pgrep
相当于ps aux后再用grep搜索
常用选项:
-u uid: effective user, 生效者, 当命令的二进制文件有suid权限时, 其他用户运行此命令时, 真正的生效者是文件的owner, 而不是发起命令的用户, pkill命令的原理也一样
-U uid: real user, 真正发起运行命令者
-t terminal: 与指定终端相关的进程
-l: 显示进程名称
-a: 显示完整格式的进程名
-P pid: 显示指定进程的子进程
范例: 查看不同终端上执行的命令
开启两个终端pts/0和pts/1
[14:46:29 root@CentOS-7-1 ~]#who am i
root pts/0 2022-09-24 14:46 (10.0.0.1)
[14:46:33 root@CentOS-7-1 ~]#who am i
root pts/1 2022-09-24 14:46 (10.0.0.1)
在pts/1上执行ping命令
[14:46:44 root@CentOS-7-1 ~]#ping 1.1.1.1
PING 1.1.1.1 (1.1.1.1) 56(84) bytes of data.
64 bytes from 1.1.1.1: icmp_seq=2 ttl=128 time=272 ms
64 bytes from 1.1.1.1: icmp_seq=4 ttl=128 time=272 ms
在pts/0上通过pgrep来查看pts/1上运行的命令以及详细信息
如果发现其他未知终端连接(假设为pts/1)上运行的命令是不被允许的, 可以搜索进程信息然后杀掉进程
# 先确定当前开启了几个终端
[14:49:42 root@CentOS-7-1 ~]#who
root pts/0 2022-09-24 14:46 (10.0.0.1)
root pts/1 2022-09-24 14:46 (10.0.0.1)
# 查看pts/1上运行的进程
[14:51:48 root@CentOS-7-1 ~]#pgrep -t pts/1
26352
26374
[14:52:25 root@CentOS-7-1 ~]#pgrep -lt pts/1 # 必须是lt, 不能是tl
26352 bash
26374 ping
[14:53:05 root@CentOS-7-1 ~]#pgrep -alt pts/1
26352 -bash
26374 ping 1.1.1.1
# 在pts/0上, 杀掉26374的ping进程
[14:53:08 root@CentOS-7-1 ~]#kill -9 26374
2.5.2 pidof
查看某个进程名对应的进程PID, 会显示该进程名开启的所有的PID
[21:38:07 root@centos-7-1 ~]#pidof bash
26512 1068
-x: 按照运行的脚本名称查看其PID
当给脚本加了执行权限, 用/路径/脚本名去执行时, 执行脚本的程序就是/bin/bash, 如果想查看具体某个脚本的执行PID, 需要用-x选项
[14:55:31 root@CentOS-7-1 /opt]#vim ping.sh
#!/bin/bash
ping 1.1.1.1
[14:55:57 root@CentOS-7-1 /opt]#chmod +x ping.sh
[14:56:00 root@CentOS-7-1 /opt]#./ping.sh
PING 1.1.1.1 (1.1.1.1) 56(84) bytes of data.
64 bytes from 1.1.1.1: icmp_seq=2 ttl=128 time=275 ms
64 bytes from 1.1.1.1: icmp_seq=3 ttl=128 time=272 ms
[14:53:31 root@CentOS-7-1 ~]#pidof -x ping.sh
26444 # 26444是ping.sh这个执行脚本的进程编号, 而脚本里边还执行了ping命令, ping命令属于该脚本的子进程. 所以不仅要kill脚本进程, 还要把脚本里面的子进程kill掉
[15:06:50 root@CentOS-7-1 ~]#pstree -p
├─sshd(803)─┬─sshd(26329)───bash(26331)───ping.sh(26444)───ping(26445)
注意: 此时如果执行kill -9 26444
, 那么ping命令还会继续执行, 只是不再占用bash终端, 但是会把结果输出在终端上. 因为虽然脚本被杀死了, 但是脚本里的ping命令还在运行, 所以还要把ping(26445)这个子进程给kill掉才能彻底关闭脚本进程
范例: 查询某个进程下的所有PID, 并且kill掉
每个终端分别运行一个cat命令
[14:59:22 root@CentOS-7-1 ~]#cat > test1.sh
[14:59:42 root@CentOS-7-1 ~]#cat > test2.sh
第三个终端上验证
[14:59:16 root@CentOS-7-1 ~]#pidof cat
26424 26422
[14:59:55 root@CentOS-7-1 ~]#kill `pidof cat`
[14:59:22 root@CentOS-7-1 ~]#cat > test1.sh
Terminated
[14:59:42 root@CentOS-7-1 ~]#cat > test2.sh
Terminated
2.6 负载查询 uptime
/proc/uptime 包含两个值, 单位是秒
- 系统启动时长
- 空闲进程总时长(按照总的CPU核数计算)
[21:54:22 root@centos-7-1 ~]#cat /proc/uptime
20264.65 20035.18
uptime和w显示以下内容
- 当前时间
- 系统已启动的时间
- 当前线上人数(几个终端正在连接)
- 系统平均负载(1,5,15分钟内的平均负载, 一般不会超过1, 超过5时建议警报)
[21:51:30 root@centos-7-1 ~]#uptime
21:54:22 up 5:18, 2 users, load average: 0.00, 0.01, 0.05
系统平均负载: 指在特定时间间隔内, 运行队列中的平均进程数, 通常每个CPU内核的当前活动进程数不大于3, 那么表示系统的性能良好, 如果每个CPU的内核任务数大于5, 那么此主机的性能有严重问题
比如: 只有一个双核CPU的Linux服务器, 当Load Avarage为6的时候就说明机器已经被充分使用
根据实际情况总结, 一般只要Load Average超过了6, 无论是几核cpu, 系统都会运行缓慢
[15:06:57 root@CentOS-7-1 ~]#lscpu
Architecture: x86_64
CPU op-mode(s): 32-bit, 64-bit
Byte Order: Little Endian
CPU(s): 1 # 单核cpu
...
2.7 显示CPU相关统计信息 mpstat
显示CPU相关信息
来自sysstat包
[22:19:45 root@centos-7-1 ~]#mpstat
Linux 3.10.0-1127.el7.x86_64 (centos-7-1.prac) 02/04/2021 _x86_64_ (1 CPU)
10:19:51 PM CPU %usr %nice %sys %iowait %irq %soft %steal %guest %gnice %idle
10:19:51 PM all 0.14 0.03 0.31 0.01 0.00 0.02 0.00 0.00 0.00 99.49
%steal: 被盗取的CPU消耗的百分比, 比如VMware运行的虚拟机内的任务是不会被Windows宿主机发现的, 但是这些进程又会消耗Windows的CPU. 这就是被盗取的CPU消耗.
2.8 查看进程实时状态 top
top提供实时查看进程状态
排序: 先执行top命令, 然后再输入选项进行排序
P: 以占据的CPU百分比排序, %CPU
M: 以占据的内存百分比排序, %MEM
T: 累计占据CPU时长, TIME+
首部信息显示:
uptime信息:l命令
tasks及cpu信息:t命令
cpu分别显示:1 (数字), 默认是多核cpu共同显示
memory信息:m命令
退出命令:q
修改刷新时间间隔:s
终止指定进程:k
保存文件:W
top命令栏位信息简介:
us:用户空间
sy:内核空间
ni:调整nice时间
id:空闲
wa:等待IO时间
hi:硬中断
si:软中断(模式切换)
st:虚拟机偷走的时间
top选项:
-d # 指定刷新时间间隔,默认为3秒
-b 全部显示所有进程
-n # 刷新多少次后退出
-H 线程模式
-p 显示pid
[22:19:51 root@centos-7-1 ~]#top
top - 22:20:45 up 5:45, 2 users, load average: 0.09, 0.06, 0.06
Tasks: 103 total, 1 running, 102 sleeping, 0 stopped, 0 zombie
%Cpu(s): 0.0 us, 0.0 sy, 0.0 ni,100.0 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
KiB Mem : 995684 total, 374068 free, 129596 used, 492020 buff/cache
KiB Swap: 2097148 total, 2097148 free, 0 used. 693492 avail Mem
# PR是top优先级, VIRT虚拟内容, RES实际占用内容, SHR共享内容
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
31332 root 20 0 162124 2148 1532 R 6.2 0.2 0:00.01 top
1 root 20 0 125496 3916 2600 S 0.0 0.4 0:04.91 systemd
2 root 20 0 0 0 0 S 0.0 0.0 0:00.00 kthreadd
范例: 在top命显示中, 杀掉进程
范例: 显示一个进程的线程信息
- 程序出问题是不一定是进程有问题, 也可能是线程问题, 可以通过此方式查看线程的运行状态
# 针对多线程进程, 比如mysqld. 这里演示polkitd进程
[15:34:52 root@CentOS-8-1 ~]#pstree -p
systemd(1)─┬─NetworkManager(725)─┬─{NetworkManager}(752)
│ └─{NetworkManager}(755)
├─VGAuthService(729)
├─agetty(894)
├─atd(890)
├─auditd(683)───{auditd}(684)
├─crond(891)
├─dbus-daemon(723)
├─polkitd(735)─┬─{polkitd}(756)
│ ├─{polkitd}(762)
│ ├─{polkitd}(766)
│ ├─{polkitd}(767)
│ └─{polkitd}(831)
[15:37:48 root@CentOS-8-1 ~]#top -H -p `pidof polkitd`
top - 15:37:59 up 4:05, 3 users, load average: 0.06, 0.69, 0.56
Threads: 6 total, 0 running, 6 sleeping, 0 stopped, 0 zombie
%Cpu(s): 0.0 us, 6.2 sy, 0.0 ni, 93.8 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
MiB Mem : 791.5 total, 364.6 free, 159.0 used, 267.9 buff/cache
MiB Swap: 2048.0 total, 2048.0 free, 0.0 used. 502.5 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
# 第一行为进程本身
735 polkitd 20 0 1625940 24012 17060 S 0.0 3.0 0:00.12 polkitd
756 polkitd 20 0 1625940 24012 17060 S 0.0 3.0 0:00.00 gmain
762 polkitd 20 0 1625940 24012 17060 S 0.0 3.0 0:00.01 gdbus
766 polkitd 20 0 1625940 24012 17060 S 0.0 3.0 0:00.00 JS Helper
767 polkitd 20 0 1625940 24012 17060 S 0.0 3.0 0:00.00 JS Helper
831 polkitd 20 0 1625940 24012 17060 S 0.0 3.0 0:00.00 polkitd
htop
: 增强版top命令, 来自EPEL源,比top功能更强
选项:
-d #: 指定延迟时间;
-u UserName: 仅显示指定用户的进程
-s COLUME: 以指定字段进行排序
子命令:
s:跟踪选定进程的系统调用
l:显示选定进程打开的文件列表
a:将选定的进程绑定至某指定CPU核心
t:显示进程树
[15:41:20 root@CentOS-8-1 ~]#yum -y install htop
2.9 查看内存 free
buffer: 写数据时使用, 把数据先提交到buffer缓冲, 然后返回写入成功, 之后再写入磁盘, 提高写速度
cache: 读数据时使用, 把数据放到缓存, 不用去磁盘读, 提高读数据
buffer和cache会占用内存空间, 并不是必须使用的. 必要时会把buffer和cache的空间用于内存使用.
[root@c6 ~]# free -h
total used free shared buffers cached
Mem: 1.8G 193M 1.6G 236K 10M 46M
-/+ buffers/cache: 136M 1.7G
Swap: 2.0G 0B 2.0G
[22:33:58 root@centos-7-1 ~]#free -h
total used free shared buff/cache available
Mem: 972M 126M 360M 7.6M 485M 675M
Swap: 2.0G 0B 2.0G
[17:21:43 root@CentOS-8-1 ~]#free -h
total used free shared buff/cache available
Mem: 791Mi 146Mi 460Mi 5.0Mi 183Mi 516Mi
Swap: 2.0Gi 0B 2.0Gi
2.10 进程对应的内存映射 pmap
当某个程序经常占用大量内存时, 可以通过pmap查看程序中对应的每个模块占用的内存大小, 来具体分析
[21:56:33 root@centos-7-1 ~]#pidof top
32151
[22:37:27 root@centos-7-1 ~]#pmap 32151
32151: top
0000000000400000 96K r-x-- top
0000000000617000 4K r---- top
0000000000618000 8K rw--- top
000000000061a000 156K rw--- [ anon ]
0000000000d4b000 364K rw--- [ anon ]
00007f58f14fc000 48K r-x-- libnss_files-2.17.so
2.11 虚拟内存信息 vmstat
显示项说明:
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.
[22:37:31 root@centos-7-1 ~]#vmstat
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
2 0 0 368372 2080 495080 0 0 11 13 35 58 0 0 99 0 0
vmstat 1 3
每一秒钟运行一次, 一共运行3次
si和so都是以内存为参照物, 当内存空间不足, 会利用swap空间, 把数据从内存写到swap, 这时对于内存来说, 数据是从内存写到swap, 因此是出, 那么so的数值就是增大
bi和bo一样, 也是以内存为参照物, 数据流向内存, 那么si或者bi就增加, 数据从内存流出, bo和so增加
-s: 显示内存的统计数据
[17:21:47 root@CentOS-8-1 ~]#vmstat -s
810488 K total memory
151724 K used memory
107500 K active memory
126888 K inactive memory
444388 K free memory
5308 K buffer memory
209068 K swap cache
2097148 K total swap
0 K used swap
2097148 K free swap
1383 non-nice user cpu ticks
21 nice user cpu ticks
1243 system cpu ticks
79450 idle cpu ticks
29 IO-wait cpu ticks
112 IRQ cpu ticks
69 softirq cpu ticks
0 stolen cpu ticks
169076 pages paged in
31410 pages paged out
0 pages swapped in
0 pages swapped out
77429 interrupts
250839 CPU context switches
1664011236 boot time
1455 forks
2.12 统计CPU和设备I/O iostat
来自sysstat包, 可以查看磁盘I/O和CPU负载情况
iostat 1 3
[22:42:03 root@centos-7-1 ~]#iostat 1 3
Linux 3.10.0-1127.el7.x86_64 (centos-7-1.prac) 02/04/2021 _x86_64_ (1 CPU)
avg-cpu: %user %nice %system %iowait %steal %idle
0.15 0.03 0.32 0.01 0.00 99.49
Device: tps kB_read/s kB_wrtn/s kB_read kB_wrtn
sda 0.77 10.34 12.58 230109 279951
scd0 0.00 0.05 0.00 1028 0
avg-cpu: %user %nice %system %iowait %steal %idle
0.00 0.00 1.00 0.00 0.00 99.00
Device: tps kB_read/s kB_wrtn/s kB_read kB_wrtn
sda 0.00 0.00 0.00 0 0
scd0 0.00 0.00 0.00 0 0
avg-cpu: %user %nice %system %iowait %steal %idle
1.00 0.00 0.00 0.00 0.00 99.00
Device: tps kB_read/s kB_wrtn/s kB_read kB_wrtn
sda 0.00 0.00 0.00 0 0
scd0 0.00 0.00 0.00 0 0
2.13 系统资源统计 dstat
(cpu, 磁盘, 网络, swap)
CentOS7上来自dstat包, CentOS8上来自pcp-system-tools, 用来代替vmstat, iostat命令
常用选项:
-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: 显示延迟最大的进程
默认就是不断刷新, 实时监控, cpu, 磁盘I/O和网络I/O
[22:53:13 root@centos-7-1 ~]#dstat
You did not select any stats, using -cdngy by default.
----total-cpu-usage---- -dsk/total- -net/total- ---paging-- ---system--
usr sys idl wai hiq siq| read writ| recv send| in out | int csw
0 0 99 0 0 0| 10k 13k| 0 0 | 0 0 | 36 58
0 0 100 0 0 0| 0 0 | 332B 5794B| 0 0 | 71 103
0 1 99 0 0 0| 0 0 | 438B 648B| 0 0 | 60 93
2.14 监视磁盘I/O iotop
查看磁盘I/O, 更专业, 来自iotop包, 会显示磁盘I/O具体是被哪个程序所消耗
[22:55:11 root@centos-7-1 ~]#iotop
Total DISK READ : 0.00 B/s | Total DISK WRITE : 0.00 B/s
Actual DISK READ: 0.00 B/s | Actual DISK WRITE: 0.00 B/s
TID PRIO USER DISK READ DISK WRITE SWAPIN IO> COMMAND
1 be/4 root 0.00 B/s 0.00 B/s 0.00 % 0.00 % systemd --switched-root --system --deserialize 22
2 be/4 root 0.00 B/s 0.00 B/s 0.00 % 0.00 % [kthreadd]
2.15 显示网络带宽使用情况 iftop
显示网络情况
默认会显示主机名
iftop -n会显示ip地址
[22:56:30 root@centos-7-1 ~]#iftop
interface: eth0
IP address is: 10.0.0.237
MAC address is: 00:0c:29:54:b7:78
Press H or ? for help 12.5Kb 25.0Kb 37.5Kb 50.0Kb 62.5Kb
mqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqvqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqvqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqvqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqvqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq
centos-7-1.prac => 10.0.0.1 9.03Kb 7.93Kb 11.6Kb
<= 1.80Kb 1.62Kb 1.67Kb
centos-7-1.prac => public1.alidns.com 0b 0b 54b
<= 0b 0b 104b
2.16 查看网络实时吞吐量 nload
Device eth0 [10.0.0.237] (1/2):
====================================================================================================================================================================================
Incoming:
Curr: 3.80 kBit/s
Avg: 2.95 kBit/s
Min: 2.54 kBit/s
Max: 3.80 kBit/s
Ttl: 41.64 MByte
Outgoing:
Curr: 11.30 kBit/s
Avg: 24.73 kBit/s
Min: 5.13 kBit/s
Max: 58.30 kBit/s
Ttl: 6.48 MByte
2.17 综合监控工具 glances
此工具可以通过EPEL源安装
[17:50:17 root@CentOS-8-1 ~]#yum -y install glances
glances支持客户端和服务端, 在服务器端开启glances, 然后在客户端查看服务端glances的结果. 要求两端的glances版本一致, 否则不兼容.
# 服务端开启glances服务
[17:58:05 root@CentOS-8-2 ~]#glances -s
Glances XML-RPC server is running on 0.0.0.0:61209
# 客户端连接到服务端
[17:51:22 root@CentOS-8-1 ~]#glances -c 10.0.0.82
2.18 查看进程打开的文件 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: 不反向解析网络名字
查看某个端口号被哪个进程占用
[23:11:03 root@centos-7-1 ~]#lsof -i:25
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
master 961 root 13u IPv4 19668 0t0 TCP localhost:smtp (LISTEN)
master 961 root 14u IPv6 19669 0t0 TCP localhost:smtp (LISTEN)
案例: 查看某个进程正在打开的文件
[18:05:47 root@CentOS-8-1 ~]#lsof -p `pidof bash`
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
bash 1301 root cwd DIR 8,2 252 50331777 /root
bash 1301 root rtd DIR 8,2 256 128 /
bash 1301 root txt REG 8,2 1219248 21398 /usr/bin/bash
bash 1301 root mem REG 8,2 2586930 50465702 /usr/lib/locale/en_US.utf8/LC_COLLATE
bash 1301 root mem REG 8,2 91144 16794181 /usr/lib64/libnss_files-2.28.so
bash 1301 root mem REG 8,2 8406312 17383812 /var/lib/sss/mc/passwd
bash 1301 root mem REG 8,2 38160 17400022 /usr/lib64/libnss_sss.so.2
bash 1301 root mem REG 8,2 4176104 16788857 /usr/lib64/libc-2.28.so
bash 1301 root mem REG 8,2 36824 16788859 /usr/lib64/libdl-2.28.so
bash 1301 root mem REG 8,2 208616 16788760 /usr/lib64/libtinfo.so.6.1
bash 1301 root mem REG 8,2 302552 16788850 /usr/lib64/ld-2.28.so
bash 1301 root mem REG 8,2 337024 50465703 /usr/lib/locale/en_US.utf8/LC_CTYPE
bash 1301 root mem REG 8,2 54 50465706 /usr/lib/locale/en_US.utf8/LC_NUMERIC
bash 1301 root mem REG 8,2 3316 5499 /usr/lib/locale/en_US.utf8/LC_TIME
bash 1301 root mem REG 8,2 286 5497 /usr/lib/locale/en_US.utf8/LC_MONETARY
bash 1301 root mem REG 8,2 57 5509 /usr/lib/locale/en_US.utf8/LC_MESSAGES/SYS_LC_MESSAGES
bash 1301 root mem REG 8,2 26998 50477406 /usr/lib64/gconv/gconv-modules.cache
bash 1301 root mem REG 8,2 34 33605497 /usr/lib/locale/en_US.utf8/LC_PAPER
bash 1301 root mem REG 8,2 77 50465705 /usr/lib/locale/en_US.utf8/LC_NAME
bash 1301 root mem REG 8,2 167 5494 /usr/lib/locale/en_US.utf8/LC_ADDRESS
bash 1301 root mem REG 8,2 59 5498 /usr/lib/locale/en_US.utf8/LC_TELEPHONE
bash 1301 root mem REG 8,2 23 5496 /usr/lib/locale/en_US.utf8/LC_MEASUREMENT
bash 1301 root mem REG 8,2 368 5495 /usr/lib/locale/en_US.utf8/LC_IDENTIFICATION
bash 1301 root 0u CHR 136,0 0t0 3 /dev/pts/0
bash 1301 root 1u CHR 136,0 0t0 3 /dev/pts/0
bash 1301 root 2u CHR 136,0 0t0 3 /dev/pts/0
bash 1301 root 3r REG 8,2 8406312 17383812 /var/lib/sss/mc/passwd
bash 1301 root 4u unix 0xffffa0eb79805100 0t0 28960 type=STREAM
bash 1301 root 255u CHR 136,0 0t0 3 /dev/pts/0
案例: 查看指定程序正在打开的文件
[18:06:25 root@CentOS-8-1 ~]#lsof -c bash
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
bash 1301 root cwd DIR 8,2 252 50331777 /root
bash 1301 root rtd DIR 8,2 256 128 /
bash 1301 root txt REG 8,2 1219248 21398 /usr/bin/bash
bash 1301 root mem REG 8,2 2586930 50465702 /usr/lib/locale/en_US.utf8/LC_COLLATE
bash 1301 root mem REG 8,2 91144 16794181 /usr/lib64/libnss_files-2.28.so
bash 1301 root mem REG 8,2 8406312 17383812 /var/lib/sss/mc/passwd
bash 1301 root mem REG 8,2 38160 17400022 /usr/lib64/libnss_sss.so.2
bash 1301 root mem REG 8,2 4176104 16788857 /usr/lib64/libc-2.28.so
bash 1301 root mem REG 8,2 36824 16788859 /usr/lib64/libdl-2.28.so
bash 1301 root mem REG 8,2 208616 16788760 /usr/lib64/libtinfo.so.6.1
bash 1301 root mem REG 8,2 302552 16788850 /usr/lib64/ld-2.28.so
bash 1301 root mem REG 8,2 337024 50465703 /usr/lib/locale/en_US.utf8/LC_CTYPE
bash 1301 root mem REG 8,2 54 50465706 /usr/lib/locale/en_US.utf8/LC_NUMERIC
bash 1301 root mem REG 8,2 3316 5499 /usr/lib/locale/en_US.utf8/LC_TIME
bash 1301 root mem REG 8,2 286 5497 /usr/lib/locale/en_US.utf8/LC_MONETARY
bash 1301 root mem REG 8,2 57 5509 /usr/lib/locale/en_US.utf8/LC_MESSAGES/SYS_LC_MESSAGES
bash 1301 root mem REG 8,2 26998 50477406 /usr/lib64/gconv/gconv-modules.cache
bash 1301 root mem REG 8,2 34 33605497 /usr/lib/locale/en_US.utf8/LC_PAPER
bash 1301 root mem REG 8,2 77 50465705 /usr/lib/locale/en_US.utf8/LC_NAME
bash 1301 root mem REG 8,2 167 5494 /usr/lib/locale/en_US.utf8/LC_ADDRESS
bash 1301 root mem REG 8,2 59 5498 /usr/lib/locale/en_US.utf8/LC_TELEPHONE
bash 1301 root mem REG 8,2 23 5496 /usr/lib/locale/en_US.utf8/LC_MEASUREMENT
bash 1301 root mem REG 8,2 368 5495 /usr/lib/locale/en_US.utf8/LC_IDENTIFICATION
bash 1301 root 0u CHR 136,0 0t0 3 /dev/pts/0
bash 1301 root 1u CHR 136,0 0t0 3 /dev/pts/0
bash 1301 root 2u CHR 136,0 0t0 3 /dev/pts/0
bash 1301 root 3r REG 8,2 8406312 17383812 /var/lib/sss/mc/passwd
bash 1301 root 4u unix 0xffffa0eb79805100 0t0 28960 type=STREAM
bash 1301 root 255u CHR 136,0 0t0 3 /dev/pts/0
#查看指定用户打开的文件
lsof -u root | more
#查看指定目录下被打开的文件,参数+D为递归列出目录下被打开的文件,参数+d为列出目录下被打开的文件
lsof +D /var/log/
lsof +d /var/log/
#查看所有网络连接,通过参数-i查看网络连接的情况,包括连接的ip、端口等以及一些服务的连接情况,例
如:sshd等。也可以通过指定ip查看该ip的网络连接情况
lsof -i –n
lsof -i@127.0.0.1
#查看端口连接情况,通过参数-i:端口可以查看端口的占用情况,-i参数还有查看协议,ip的连接情况等
lsof -i :80 -n
#查看指定进程打开的网络连接,参数-i、-a、-p等,-i查看网络连接情况,-a查看存在的进程,-p指定进程
lsof -i –n -a -p 9527
#查看指定状态的网络连接,-n:no host names, -P:no port names,-i TCP指定协议,-s指定协议
状态通过多个参数可以清晰的查看网络连接情况、协议连接情况等
lsof -n -P -i TCP -s TCP:ESTABLISHED
#查看由登陆用户启动而非系统启动的进程
lsof /dev/pts/1 # 指定终端名称
案例: vim打开一个文件时, 实际打开的是该文件的临时.swap文件
[18:09:54 root@CentOS-8-1 ~]#vim test.sh
[18:10:22 root@CentOS-8-1 ~]#ls -a -l
-rw------- 1 root root 12288 Sep 24 18:10 .test.sh.swp
[18:11:41 root@CentOS-8-1 ~]#lsof -p `pidof vim`
...
vim 1778 root 5u REG 8,2 12288 50454302 /root/.test.sh.swp
案例: 利用lsof恢复正在使用中的误删除的文件
必须是正在被使用的文件, 才能用以下方法恢复
1. messages日志文件是一直被rsyslogd占用的
[23:14:36 root@centos-7-1 ~]#lsof /var/log/messages
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
rsyslogd 810 root 6w REG 8,2 704472 34092214 /var/log/messages
2. 删除messages文件
[23:15:58 root@centos-7-1 ~]#rm -rf /var/log/messages
[23:16:33 root@centos-7-1 ~]#ls -l /var/log/messages
ls: cannot access /var/log/messages: No such file or directory
3. 删除后在lsof的输出中仍能看到, 状态为deleted
[23:16:42 root@centos-7-1 ~]#lsof | grep /var/log/messages
rsyslogd 810 root 6w REG 8,2 704472 34092214 /var/log/messages (deleted)
in:imjour 810 813 root 6w REG 8,2 704472 34092214 /var/log/messages (deleted)
rs:main 810 814 root 6w REG 8,2 704472 34092214 /var/log/messages (deleted)
4. 通过fd文件描述符来恢复数据
[23:17:09 root@centos-7-1 ~]#ls /proc/810/fd
0 1 2 3 4 5 6 7 8 9
[23:19:17 root@centos-7-1 ~]#ls /proc/810/fd -l
total 0
lr-x------ 1 root root 64 Feb 4 16:35 0 -> /dev/null
l-wx------ 1 root root 64 Feb 4 16:35 1 -> /dev/null
l-wx------ 1 root root 64 Feb 4 16:35 2 -> /dev/null
lr-x------ 1 root root 64 Feb 4 16:35 3 -> anon_inode:inotify
lrwx------ 1 root root 64 Feb 4 16:35 4 -> socket:[19054]
lr-x------ 1 root root 64 Feb 4 16:35 5 -> /run/log/journal/faf6cab1d01a401daa5c2e37cab6e4fa/system.journal
l-wx------ 1 root root 64 Feb 4 16:35 6 -> /var/log/messages (deleted) # fd6就是被我们删除的messages文件使用的文件描述符
l-wx------ 1 root root 64 Feb 4 16:35 7 -> /var/log/cron
l-wx------ 1 root root 64 Feb 4 16:35 8 -> /var/log/secure
l-wx------ 1 root root 64 Feb 4 16:35 9 -> /var/log/maillog
[23:19:27 root@centos-7-1 ~]#cat /proc/810/fd/6 > /var/log/messages # 读出来文件描述符, 追加到messages里
[23:20:09 root@centos-7-1 ~]#ls -l /var/log/messages
-rw-r--r-- 1 root root 704541 Feb 4 23:20 /var/log/messages
2.19 CentOS 8 新特性 cockpit
Cockpit 是CentOS 8 取入的新特性,是一个基于 Web 界面的应用,它提供了对系统的图形化管理. 用来监控单机服务器状态.
- 监控系统活动(CPU、内存、磁盘 IO 和网络流量)
- 查看系统日志条目
- 查看磁盘分区的容量
- 查看网络活动(发送和接收)
- 查看用户帐户
- 检查系统服务的状态
- 提取已安装应用的信息
- 查看和安装可用更新(如果以 root 身份登录)并在需要时重新启动系统
- 打开并使用终端窗口
范例:使用cockpit
安装cockpit, 并启动服务
[18:25:42 root@CentOS-8-1 ~]#yum -y install cockpit
[18:26:04 root@CentOS-8-1 ~]#systemctl enable --now cockpit.socket
打开浏览器, 访问以下地址
https://cockpit服务端ip:9090
2.20 信号发送 kill
kill: 内部命令, 可用来向进程发送控制信号, 以实现对进程管理, 每个信号对应一个数字, 信号名称以SIG开头(可省略), 不区分大小写
查看帮助:man 7 signal
- 查看当前系统可用信号
kill -l
trap -l
- 常用信号
1 --> SIGHUP 无须关闭进程而让其重读配置文件
配置文件只有在进程第一次启动时才读取, 后续只要不重启, 就不会重读配置文件
但是一旦重启, 服务就会中断, 影响用户访问. 利用1信号可以在不中断进程运行的情况下, 重新读取配置文件, 尽量减少对用户访问的影响
一般来说, 正在访问的用户是不会收到配置变更的影响的, 新访问的用户才会受影响
2 --> SIGINT 中止正在运行的进程, 相当于ctrl+c
3 --> SIGQUIT 相当于ctrl + \
9 --> SIGKILL 强制杀死正在运行的进程
15 --> SIGTERM 终止正在运行的进程, 默认信号
18 --> SIGCONT 继续运行
19 --> SIGSTOP 后台休眠
指定信号的方法 :
- 信号的数字标识:1, 2, 9
- 信号完整名称:SIGHUP,sighup
- 信号的简写名称:HUP,hup
- 向进程发送信号, 三种方式都支持信号
按PID
kill -1 PID
按进程名称
killall 进程名称, killall来自psmisc包
killall ping # 所有ping进程都被停止
按照模式
pkill [options] PATTERN
pkill常用选项
-SIGNAL
-u uid: effective user, 生效者, 当命令的二进制文件有suid权限时, 其他用户运行此命令时, 真正的生效者是文件的owner, 而不是发起命令的用户, pgrep命令的原理也一样
以passwd为例, 其二进制文件有suid权限, 所以任何人在执行passwd程序时, 真正生效的用户是root
-U uid: real user, 真正发起运行命令者, 谁执行的命令就会kill谁, 和特殊权限无关
-t terminal: 与指定终端相关的进程
-l: 显示进程命名(pgrep可用)
-a: 显示完整格式的进程名(pgrep可用)
-P pid: 显示指定进程的子进程
- 范例: 利用 0 信号实现进程的健康性检查
If sig is 0, then no signal is sent, but error checking is still performed.
此方式有局限性, 即使进程处于僵尸态或者停止态, 0信号仍然认为进程是健康的
# 在一个终端执行ping命令
[18:26:16 root@CentOS-8-1 ~]#ping 1.1.1.1
# 另一个终端进行检查
[18:43:29 root@CentOS-8-1 ~]#killall -0 ping
[18:43:42 root@CentOS-8-1 ~]#echo $?
0
[18:43:44 root@CentOS-8-1 ~]#killall -0 httpd
httpd: no process found
[18:45:33 root@CentOS-8-1 ~]#echo $?
1
- 范例: 给httpd发送1信号重新读取配置文件
- 安装httpd服务
[18:58:11 root@CentOS-7-1 ~]#yum -y install httpd
[18:58:33 root@CentOS-7-1 ~]#systemctl enable --now httpd
Created symlink from /etc/systemd/system/multi-user.target.wants/httpd.service to /usr/lib/systemd/system/httpd.service
- 制作默认页面
[18:58:39 root@CentOS-7-1 ~]#echo /var/www/html/index.html > /var/www/html/index.html
- 将页面存放路径改为
/data/www
- 将页面存放路径改为
[18:59:45 root@CentOS-7-1 ~]#mkdir -p /data/www
[18:59:50 root@CentOS-7-1 ~]#echo /data/www/index.html > /data/www/index.html
[18:59:12 root@CentOS-7-1 ~]#vim /etc/httpd/conf/httpd.conf
#DocumentRoot "/var/www/html"
DocumentRoot "/data/www"
#<Directory "/var/www">
<Directory "/data">
AllowOverride None
# Allow open access:
Require all granted
</Directory>
# Further relax access to the default document root:
#<Directory "/var/www/html">
<Directory "/data/www">
- 验证服务重启前的httpd进程编号
[19:01:59 root@CentOS-7-1 ~]#pstree -p | grep httpd
|-httpd(1178)-+-httpd(1179)
| |-httpd(1180)
| |-httpd(1181)
| |-httpd(1182)
| |-httpd(1183)
| `-httpd(1184)
- 重启服务
[19:02:43 root@CentOS-7-1 ~]#systemctl restart httpd
[19:22:03 root@CentOS-7-1 ~]#pstree -p | grep httpd
|-httpd(1442)-+-httpd(1443) # 可以看到无论是master进程还是slave进程都发生变化, 所以重启服务时, 正在访问的用户会收到影响
| |-httpd(1444)
| |-httpd(1445)
| |-httpd(1446)
| `-httpd(1447)
- 将页面存放路径改回
/var/www/html
- 将页面存放路径改回
DocumentRoot "/var/www/html"
#
# Relax access to content within /var/www.
#
<Directory "/var/www">
AllowOverride None
# Allow open access:
Require all granted
</Directory>
# Further relax access to the default document root:
<Directory "/var/www/html">
- 给httpd发送1信号, 重读配置文件, 再查看重启后的进程编号
[19:23:41 root@CentOS-7-1 ~]#kill -1 1442 # 给master进程发送信号
[19:23:50 root@CentOS-7-1 ~]#pstree -p | grep httpd
|-httpd(1442)-+-httpd(1450) # 可以看到master进程的PID没有发生变化
| |-httpd(1451)
| |-httpd(1452)
| |-httpd(1453)
| `-httpd(1454)
2.21 作业管理
Linux的作业控制
前台运行: 通过终端启动, 且启动后一直占据终端, 如bc命令, ping命令
后台运行: 可通过终端启动, 但启动后立即转入后台运行, 释放终端资源, 如bash命令
如果前台命令有输出到终端, 那么在输出结束前执行命令是不会立即返回结果的, 需要等到前台命令输出结束, 执行的命令才会返回结果
前台运行的命令用ctrl+c即可终止, 后台运行的命令用kill
范例: ctrl + z, 让前台命令变成后台停止(T状态)
[18:45:35 root@CentOS-8-1 ~]#ping 1.1.1.1
PING 1.1.1.1 (1.1.1.1) 56(84) bytes of data.
64 bytes from 1.1.1.1: icmp_seq=1 ttl=128 time=274 ms
64 bytes from 1.1.1.1: icmp_seq=5 ttl=128 time=274 ms
^Z
[1]+ Stopped ping 1.1.1.1
[19:10:01 root@CentOS-8-1 ~]#ps aux | grep ping
root 5626 0.0 0.2 32408 2276 pts/0 T 19:45 0:00 ping 1.1.1.1
root 5643 0.0 0.1 12108 1044 pts/1 R+ 19:47 0:00 grep --color=auto ping
范例: 18信号, 让后台停止的命令进入后台运行
[19:10:01 root@CentOS-8-1 ~]#ps aux | grep ping
root 5626 0.0 0.2 32408 2276 pts/0 T 19:45 0:00 ping 1.1.1.1
root 5643 0.0 0.1 12108 1044 pts/1 R+ 19:47 0:00 grep --color=auto ping
[19:47:25 root@CentOS-8-1 ~]#kill -18 5626
收到18信号后, ping命令会在后台运行, 但是结果仍会输出在前台, 不过并不影响其他命令的执行
# ping会进入S状态, 表面上正在执行返回结果, 但实际大部分时间都在睡眠, CPU需要等待网络IO, 等待对方主机返回ping的结果信息
[19:52:36 root@CentOS-8-1 ~]#ps aux | grep ping
root 5626 0.0 0.2 32408 2276 pts/0 S 19:45 0:00 ping 1.1.1.1
root 5730 0.0 0.1 12108 1100 pts/1 R+ 19:57 0:00 grep --color=auto ping
此时, 一旦关闭了终端, 那么ping命令会结束运行, 进程也会被删除
让作业运行于后台
1. 运行中的前台作业: ctrl + z, 先让其处于stop状态, 停止在后台, 然后执行kill -18, 再让其运行在后台
2. 尚未启动的作业: CMD &, 直接运行在后台
CMD & 启动的后台作业虽然会被送往后台运行, 但是其依然与终端有关, 退出启动命令的终端, 将关闭后台作业, 程序关闭
如果希望送往后台后, 与终端脱离关系, 可以使用下面命令
使用nohup运行命令后, 如果终端关闭, 那么systemd会变成其父进程, systemd是不会被关闭的, 所以即使关闭了终端,命令还会执行
nohup CMD &> /dev/null &
nohup命令
前台运行的命令是和终端绑定的, 因此前台命令要依附于父进程运行, 也就是bash终端, 所以一旦终端关闭, bash进程关闭, 那么前台进程就没有了父进程, 也就被关闭了
使用&
虽然会让前台命令运行在后台, 但是仍然是和终端绑定的, 终端关闭, 命令也就关闭了
范例: nohup ping 127.0.0.1
nohup将前台执行的命令放到后台运行, 可以解除进程和终端的绑定关系, 即使终端关闭, 也不会影响后台程序的运行. 并且会把输出结果默认持续追加到当前工作目录的nohup.out文件
[20:46:35 root@CentOS-8-1 ~]#nohup ping 127.0.0.1
查看ping的PID
[20:46:42 root@CentOS-8-1 ~]#pstree -p
│ ├─sshd(5867)───sshd(5869)───bash(5870)───ping(6273)
关闭执行nohup ping的终端, 再次查看ping的PID
[20:46:56 root@CentOS-8-1 ~]#pstree -p
systemd(1)─┬─NetworkManager(718)─┬─{NetworkManager}(742)
│ └─{NetworkManager}(745)
├─VGAuthService(716)
├─agetty(877)
├─atd(870)
├─auditd(676)───{auditd}(677)
├─crond(872)
├─dbus-daemon(712)
├─gpg-agent(2581)
├─gpg-agent(3528)
├─gpg-agent(3945)
├─gpg-agent(3958)
├─packagekitd(2473)─┬─{packagekitd}(2474)
│ └─{packagekitd}(2477)
├─ping(6273) # 可以发现ping变成了systemd的子进程
范例: nohup ping 127.0.0.1 &
nohup
命令配合&
后台运行命令时会把执行的命令的输出存放到当前工作目录的nohup.out文件下
[20:41:02 root@CentOS-8-1 ~]#clear
[20:41:03 root@CentOS-8-1 ~]#nohup ping 127.0.0.1 &
[3] 6187
[20:41:24 root@CentOS-8-1 ~]#nohup: ignoring input and appending output to 'nohup.out'
[20:41:32 root@CentOS-8-1 ~]#cat nohup.out
PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.021 ms
64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.028 ms
64 bytes from 127.0.0.1: icmp_seq=3 ttl=64 time=0.028 ms
64 bytes from 127.0.0.1: icmp_seq=4 ttl=64 time=0.028 ms
64 bytes from 127.0.0.1: icmp_seq=5 ttl=64 time=0.029 ms
64 bytes from 127.0.0.1: icmp_seq=6 ttl=64 time=0.029 ms
64 bytes from 127.0.0.1: icmp_seq=7 ttl=64 time=0.032 ms
64 bytes from 127.0.0.1: icmp_seq=8 ttl=64 time=0.029 ms
64 bytes from 127.0.0.1: icmp_seq=9 ttl=64 time=0.027 ms
64 bytes from 127.0.0.1: icmp_seq=10 ttl=64 time=0.026 ms
范例: nohup ping 127.0.0.1 &> /dev/null &
将命令放到后台运行, 取消输出
[20:57:53 root@CentOS-8-1 ~]#nohup ping 127.0.0.1 &> /dev/null &
[1] 6444
查看当前终端所有作业
jobs: 只对当前终端有效
作业控制
fg [%]JOBNUMBER: 把指定的后台作业调回前台运行
bg [%]JOBNUMBER: 让后台停止的作业继续在后台运行, 等价于kill -18
kill [%]JOBNUMBER: 终止指定的作业
范例: fg, bg, jobs,前台后台综合案例
# ping默认是前台运行
[20:07:37 root@CentOS-8-1 ~]#ping 127.0.0.1
PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.020 ms
64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.030 ms
[20:17:10 root@CentOS-8-1 ~]#ps aux | grep ping
root 5948 0.0 0.2 32408 2428 pts/1 S+ 20:14 0:00 ping 127.0.0.1
使用ctrl+z让其进入后台停止
64 bytes from 127.0.0.1: icmp_seq=159 ttl=64 time=0.032 ms
64 bytes from 127.0.0.1: icmp_seq=160 ttl=64 time=0.027 ms
^Z
[1]+ Stopped ping 127.0.0.1
[20:17:12 root@CentOS-8-1 ~]#ps aux | grep ping
root 5948 0.0 0.2 32408 2428 pts/1 T 20:14 0:00 ping 127.0.0.1
使用bg让其运行在后台
# 先确定jobs编号
[20:24:36 root@CentOS-8-1 ~]#jobs
[1]- Stopped ping 127.0.0.1
[20:25:34 root@CentOS-8-1 ~]#bg 1
[1]- ping 127.0.0.1 &
[20:26:09 root@CentOS-8-1 ~]#64 bytes from 127.0.0.1: icmp_seq=161 ttl=64 time=0.027 ms
64 bytes from 127.0.0.1: icmp_seq=162 ttl=64 time=0.030 ms
64 bytes from 127.0.0.1: icmp_seq=163 ttl=64 time=0.033 ms
64 bytes from 127.0.0.1: icmp_seq=164 ttl=64 time=0.037 ms
64 bytes from 127.0.0.1: icmp_seq=165 ttl=64 time=0.031 ms
ls
anaconda-ks.cfg 'axo pid,cmd,psr,ni,pri,rtprio' Sys_Init.sh
[20:26:14 root@CentOS-8-1 ~]#64 bytes from 127.0.0.1: icmp_seq=166 ttl=64 time=0.032 ms
64 bytes from 127.0.0.1: icmp_seq=167 ttl=64 time=0.030 ms
此时ping命令运行在后头, 结果输出在前台, 所以可以执行fg 1
让其运行在前台
f64 bytes from 127.0.0.1: icmp_seq=226 ttl=64 time=0.030 ms
g 1
ping 127.0.0.1
64 bytes from 127.0.0.1: icmp_seq=227 ttl=64 time=0.030 ms
64 bytes from 127.0.0.1: icmp_seq=228 ttl=64 time=0.032 ms
64 bytes from 127.0.0.1: icmp_seq=229 ttl=64 time=0.029 ms
ls
64 bytes from 127.0.0.1: icmp_seq=230 ttl=64 time=0.031 ms
ls
64 bytes from 127.0.0.1: icmp_seq=231 ttl=64 time=0.030 ms
64 bytes from 127.0.0.1: icmp_seq=232 ttl=64 time=0.030 ms
[20:27:12 root@CentOS-8-1 ~]#ps aux | grep ping
root 5948 0.0 0.2 32408 2428 pts/1 S+ 20:14 0:00 ping 127.0.0.1
2.22 并行运行
默认情况输入的命令都是按照顺序执行, 一旦某个命令执行较长, 就会影响后面命令的执行
[21:02:28 root@CentOS-8-1 ~]#ping -c3 127.0.0.1; ping -c3 127.0.0.2
PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.023 ms
64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.031 ms
64 bytes from 127.0.0.1: icmp_seq=3 ttl=64 time=0.032 ms
--- 127.0.0.1 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 61ms
rtt min/avg/max/mdev = 0.023/0.028/0.032/0.007 ms
PING 127.0.0.2 (127.0.0.2) 56(84) bytes of data.
64 bytes from 127.0.0.2: icmp_seq=1 ttl=64 time=0.017 ms
64 bytes from 127.0.0.2: icmp_seq=2 ttl=64 time=0.029 ms
64 bytes from 127.0.0.2: icmp_seq=3 ttl=64 time=0.029 ms
--- 127.0.0.2 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 49ms
rtt min/avg/max/mdev = 0.017/0.025/0.029/0.005 ms
利用后台执行, 实现并行功能, 即同时运行多个进程, 提高效率
方法1: 在脚本中实现
cat all.sh
f1.sh&
f2.sh&
f3.sh&
方法2:
(f1.sh&);(f2.sh&);(f3.sh&)
方法3:
f1.sh&f2.sh&f3.sh&
案例: 实现并行扫描网段的主机
#!/bin/bash
NET=10.0.0
for i in {1..254}; do
{ # 长命令建议用括号括起来, 也可以用(), 或者不用括号也行
ping -c1 -W1 ${NET}.${i} &> /dev/null && echo "${NET}.$i is up" || echo "${NET}.$i is down"
}&
done
wait # 后台命令执行结束, 主动返回终端, 否则执行完, 会卡住, 还要手动退出脚本