14: Linux进程管理

1 进程和内存管理

内核功能:

进程管理
内存管理
文件系统管理
网络管理
驱动程序管理
安全管理
...

单核CPU如何同时处理多个进程?

image.png

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)

进程, 线程和携程

图片.png
  • 进程: 运行中的程序的一个副本, 是被载入内存的一个指令集合, 是资源分配的单位
执行一个命令, 其磁盘文件会被加载到内存, 启动为进程
进程是资源分配的单位, 包括代码, 访问的文件, 数据, 占用的地址空间, 线程和携程信息
进程包含程序代码 
进程也可以查看或者编辑其他的文件, 这就需要把进程访问的文件也加载到内存, 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 进程结构

image.png
内核把进程放在叫做任务队列(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, 后备缓冲器, 用于保存虚拟地址和物理地址映射关系的缓存. 之后再进行虚拟内存到物理内存的映射时, 就可以直接从缓存中获取数据
image.png

1.3.3 用户空间和内核空间

操作系统的内存空间分为用户空间(进程)和内核空间(内核)
每个进程认为自己独占整个用户空间
用户空间存放了进程的代码段, 数据, BSS, 以及堆栈信息
image.png
image.png

1.3.4 c代码和内存布局之间的对应关系

image.png

每个进程都包括5中不同的数据段

  • 代码段: 用来存放可执行文件的操作指令, 也就是说它是可执行程序在内存中的镜像. 代码段需要防止在运行时被非法修改, 所以只准许读取操作, 而不允许写操作 -- 也就是代码段是不可写的
  • 数据段: 用来存放可执行文件中已初始化的全局变量, 也就是存放程序静态分配的变量和全局变量
  • BSS段: Block Started by Symbol, 以符号开始的块, BSS段包含了程中未初始化的全局变量, 在内存中BSS段全部置位0
  • 堆(heap): 存放数组和对象, 堆是用于存放进程进行中被动态分配的内存段, 它的大小不固定, 可以扩张也可以缩减. 当进程调用malloc的函数分配内存时, 新分配的内存就被动态添加到堆上; 当利用free等函数释放内存时, 被释放的内存从堆中被剔除(堆被缩减). 堆的数据可以动态存取, 没有后进先出, 或者先进先出的特点
  • 栈: 栈是用户存放程序临时创建的局部变量, 也就是函数{}中定义的变量, 但不包括static声明的变量, static意味着在数据段中存放变量. 除此之外, 在函数被调用时, 其参数也会被压入发起调用的进程栈中, 并且待到调用结束后, 函数的返回值也会被存放回栈中. 由于栈区的后进先出特点, 所以栈区特别方便用来恢复/保存调用现场. 可以把堆栈看成一个寄存、交换临时数据的内存区域
image.png

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 进程状态

图片.png

进程的基本状态

创建状态: 进程在创建时需要申请一个空白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   # 杀死子进程

image.png

方法1: 恢复父进程

[12:20:51 root@CentOS-8-1 ~]#kill -18 1364
image.png

方法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  # 杀死子进程

image.png
[12:28:02 root@CentOS-8-1 ~]#kill -9 1364

1.5 LRU算法

LRU: Least Recently Used, 近期最少使用算法, 释放内存
近期被使用最少的内存数据将被淘汰, 如果一个数据马上要被淘汰了, 又被访问, 那么就要重新排队等着被淘汰
image.png

范例:

假设序列为 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优先级

不同的优先级都遵循从右到左, 优先级递增; 非系统进程一般属于右侧的优先级划分

图片.png
系统优先级: 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, 在系统引导过程中启动的进程,开机就会运行, 和终端无关
  • 前台进程:跟终端相关,通过终端启动的进程
image.png

注意:两者可相互转化

按进程资源使用的分类:

  • 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
image.png

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命显示中, 杀掉进程

image.png
image.png
image.png
image.png

范例: 显示一个进程的线程信息

  • 程序出问题是不一定是进程有问题, 也可能是线程问题, 可以通过此方式查看线程的运行状态
# 针对多线程进程, 比如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
image.png

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
图片.png

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
image.png

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
image.png
image.png
image.png
image.png

2.20 信号发送 kill

kill: 内部命令, 可用来向进程发送控制信号, 以实现对进程管理, 每个信号对应一个数字, 信号名称以SIG开头(可省略), 不区分大小写

查看帮助:man 7 signal
  1. 查看当前系统可用信号
kill -l
trap -l
  1. 常用信号
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
  1. 向进程发送信号, 三种方式都支持信号

按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: 显示指定进程的子进程
  1. 范例: 利用 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

  1. 范例: 给httpd发送1信号重新读取配置文件
    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
    1. 制作默认页面
[18:58:39 root@CentOS-7-1 ~]#echo /var/www/html/index.html > /var/www/html/index.html
image.png
    1. 将页面存放路径改为/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">
    1. 验证服务重启前的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)
    1. 重启服务
[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)
    1. 将页面存放路径改回/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">
    1. 给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)
image.png

2.21 作业管理

Linux的作业控制
前台运行: 通过终端启动, 且启动后一直占据终端, 如bc命令, ping命令
后台运行: 可通过终端启动, 但启动后立即转入后台运行, 释放终端资源, 如bash命令
如果前台命令有输出到终端, 那么在输出结束前执行命令是不会立即返回结果的, 需要等到前台命令输出结束, 执行的命令才会返回结果
image.png

前台运行的命令用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命令会在后台运行, 但是结果仍会输出在前台, 不过并不影响其他命令的执行


image.png
# 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 # 后台命令执行结束, 主动返回终端, 否则执行完, 会卡住, 还要手动退出脚本
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容