25 HUP信号,僵尸进程与孤儿进程

427次阅读
没有评论

共计 7981 个字符,预计需要花费 20 分钟才能阅读完成。

一. 关于 HUP 信号

1. 什么是 HUP 信号

  • hup 信号除了在上一篇讲的从新加载配置文件功能外还具有另外一种功能

  • 当用户注销(exit, logout, Ctrl + d), 或者网络断开时, 终端会收到 Linux HUP 信号

  • HUP 信号会使其关闭所有子进程, 这样就会关闭你不想关闭的进程

  • 解决方法:

python
1. 让进程忽略 Linux HUP 信号
2. 让进程运行在新的终端里, 从而不属于当前终端

2.nohup命令

  • nohup 顾名思义, 就是忽略 hup 信号
  • nohup 通常与 & 符号连用, 让提交的命令忽略 Linux HUP 信号
  • 用法
🌵nohup 使用十分方便,只需在要处理的命令前加上 "nohup" 即可,一般配合 "&" 符号将其放入后台
# nohup [命令] &
  • 示例
🌵在终端 a 使用 "nohup" 运行一条 "ping" 命令
[root@shawn ~]# nohup ping baidu.com &> /dev/null &

🌵在终端 b 过滤出 "ping" 进程的信息
[root@shawn ~]# ps -elf | grep [p]ing
4 S root  57838  57801  0  80  0 - 37522 poll_s 19:10 pts/1  00:00:00 ping baidu.com

🌵我们 "kill" 掉该进程的父进程 "57801"(终端 a), 并再次查看
[root@shawn ~]# kill -9 57801
[root@shawn ~]# ps -elf | grep [p]ing
4 S root   57838  1  0  80   0 - 37522 poll_s 19:10 pts/1  00:00:00 ping baidu.com
🌵可以发现终端 a 关闭后, 其下的子进程并没有关闭, 但父进程 PID 变成了 "1", 即 "systemd" 进程

3.setsid命令

  • 原理与 nohup 一样
  • setsid 是直接将进程的父进程 PID 设置成 1
  • 即直接让 systemd 成为该进程的父进程, 那么除非 systemd 结束, 该子进程才会结束
  • 用法
# setsid [命令]   (& 符号可加可不加)
  • 示例
🌵在终端 a 中使用 "setsid" 命令运行一条 "sleep" 命令
[root@shawn ~]#setsid sleep 200000

🌵关闭终端 a, 在终端 B 中查看进程信息, 发现进程还在运行, 并且父进程 PID 为 "1"
[root@shawn ~]#ps -elf | grep [s]leep
0 S root  63319  1  0  80  0 - 27013 hrtime 20:56 ?  00:00:00 sleep 100000 

4. 在子 shell 中提交任务

  • 什么是子 Shell
就是从当前的的 "shell" 环境中开的一个新 "shell"
  • 用法
# ([命令] &)
🌵圆括号结构能够强制将其中的命令运行在子 Shell 中
  • 示例
🌵在终端 a 中使用 "( )" 结构运行一条 "ping" 命令
[root@shawn ~]#(ping baidu.com&>/dev/null &)

🌵关闭终端 a, 在终端 B 中查看进程信息, 发现进程还在运行, 并且父进程 PID 为 "1"
[root@shawn ~]#ps -elf | grep [p]ing
4 S root  64003  1  0  80  0 - 37522 poll_s 21:09 pts/1  00:00:00 ping baidu.com

5.screen命令

  • 什么是screen
Screen 是一个命令行终端切换的软件
在 "screen" 环境下, 所有的会话都将独立运行
使用前先安装它 "yum install screen -y"
  • 用法
# screen [后面接一些命令或用法, 不唯一, 往下会演示]
  • 常用命令选项
-ls 显示现有的 screen 会话, 格式为(pid.tty.host)
-r [name/PID] 恢复一个 screen 会话
-S [name] 创建一个 screen 会话并命名
-x 共享一个会话演示, 可以操作(多个屏幕)
-wipe 先检查所有 screen 会话, 然后删除无法使用 screen 会话
Ctrl + d / exit 退出 screen 会话
Ctrl + a,Ctrl + d 隐藏当前 screen 会话窗口, 切到上一个窗口 / 终端
  • screen运行机制

使用 screen 运行一个 vim

screen vim nnn.txt然后查看进程信息

25 HUP 信号, 僵尸进程与孤儿进程

可以发现一共产生了这三个进程, 画个图👇👇👇👇👇

25 HUP 信号, 僵尸进程与孤儿进程

我们将 screen 这个进程 kill掉看看结果

25 HUP 信号, 僵尸进程与孤儿进程

发现对 vim 进程真的没有影响, 而 SCREEN 也被 systemd 接管了

这不就是我们使用 screen 想要的结果吗

  • 示例
🌵开启一个窗口并指定名字, 也可以不指定
# screen -S song1

🌵在 screen 会话窗口中的退出操作
[root@shawn ~]#logout
bash: logout: 不是登录 shell: 使用 `exit'   #所以这种退出方式不可用
1."Ctrl + d" 以及 "# exit" 可用
2."Ctrl + a" 紧接着 "Ctrl + d" 可以将这个会话放在后台, 并切回到前一个窗口 / 终端(注意并不是关闭)

🌵显示所有的 screen 会话, 就是列出你创建的 screen 会话(里面可能会有一些无法使用的会话)
# screen -ls   
"kill" 命令通过进程号杀掉一个 "screen" 会话, 这种无效会话会在 "screen -ls" 中显示出来

🌵清除掉 "kill" 杀掉的无效会话
# screen -wipe
这个命令运行完后, 无效的会话后面会出现(Remove), 然后就被清除掉了

🌵恢复之前放在后台 (或者是隐藏) 的 screen 会话窗口
# screen -r song1

🌵共享一个 screen 会话屏幕
# screen -x song1
在不同的终端里面都可以通过 "-x" 后面接名字链接到这个 screen 会话窗口, 并进行操作

🌵使用 "screen" 执行一个 "vim nnn.txt" 操作
# screen vim nnn.txt
执行后直接就是以一个新的窗口打开 "vim" 进入到命令模式, 退出 "vim" 将退出该窗口 / 会话

二. 孤儿进程

1. 什么是孤儿进程

  • 当一个父进程创建了多个子进程, 子进程再创建子子进程等等
  • 父进程因正常 运行完毕 或其他情况 被干掉 的时候, 它的子进程就变成了 孤儿进程
  • 为了避免孤儿进程完成任务后没有父亲通知操作系统回收资源
  • 于是 PID 为 "1" 的顶级进程 systemd 就接手了这个孤儿进程
  • systemd 相当于一个孤儿院, 但凡是孤儿进程都会成为它的子进程

2. 孤儿进程演示

  • 先在一个虚拟终端里开启一个 Bash 进程, 把他当做父进程
  • 紧接着开启一个 "sleep 1000 &" 进程, 把它当做子进程
  • 然后在另一个虚拟终端查看这两个进程信息

25 HUP 信号, 僵尸进程与孤儿进程

  • 再杀掉 sleep 的父进程 Bash 看看结果如何

25 HUP 信号, 僵尸进程与孤儿进程

  • 图示

25 HUP 信号, 僵尸进程与孤儿进程

三. 僵尸进程

1. 什么是僵尸进程

  • 这是 Linux 出于 好心 的设计

  • 一个父进程开启了一堆子进程, 当 子进程 比父进程 先运行完(死掉)

  • 操作系统会 释放 子进程占用的 重型资源(内存空间, CPU 资源, 打开的文件)

  • 但会 保留 子进程的 关键信息(PID, 退出状态, 运行时间等)

  • 目的是为了让父进程能随时 查看 自己的 子进程信息(不管该子进程有没有死掉)

  • 这种已经死掉的子进程都会进入僵尸状态, ''僵尸进程'' 是 Linux 系统的一种数据结构

2. 僵尸进程回收 ---- 概念

  • 操作系统保留子进程信息供父进程查看
  • 当父进程觉得 不再需要 查看的时候, 会向操作系统发送一个 wait / waitpid 系统调用
  • 于是操作系统 再次清理 僵尸进程的残余信息

3. 僵尸进程回收 ---- 实际

  • 优秀的开源软件
这些软件在开启子进程时, 父进程内部会及时调用 "wait" / "waitpid" 通知操作系统来回收僵尸进程
  • 水平良好的开发者
功底深厚, 知道父进程要对子进程负责
会在父进程内部考虑到调用 "wait" / "waitpid" 通知操作系统回收僵尸进程
但是发起系统调用时间可能慢了一点
于是我们就可以使用 "ps aux | grep [z]+" 命令查看到僵尸进程
  • 水平非常低的开发者
技术半吊子, 只知道开子进程, 父进程也不结束, 并在那一直开子进程, 不知道什么是僵尸进程
系统调用 "wait" / "waitpid" 也没有听说过
于是计算机会堆积许多的僵尸进程, 占用着大量的 "pid",(每启动一个进程就会分配一个 "pid 号 ")
计算机进入一个奇怪的现象: 内存够用, 硬盘充足,CPU 空闲, 但新的程序无法启动
这就是因为 "PID" 不够用了

4. 如何清理僵尸进程

  • 针对良好的开发者
我们可以手动发信号给父进程: "# kill -CHLD [父进程的 PID]"
通知父进程快点向操作系统发起系统调用 "wait" / "waitpid" 来清理变成僵尸的儿子们
  • 针对半吊子水平的开发者
这种情况子下, 我们只能将父进程终结, 因为你发给它的信号不会得到回应
父进程被杀死," 僵尸进程 " 将会变成 " 僵尸孤儿进程 "
但凡是 " 孤儿进程 " 都会被 Linux 系统中 "PID" 为 "1" 的顶级进程 "systemd" 回收
"systemd" 会发起系统调用 "wait" / "waitpid" 来通知操作系统清理僵尸进程
# Centos7 的顶级进程为 systemd
# Centos6 的顶级进程为 init

四. 查看网络状态

1. 命令

netstat

2. 选项

-t tcp 协议
-u udp 协议
-l listen
-p PID/Program name
-n 不反解, 不将 IP 地址解析为主机号, 不将端口号解析成协议名

3. 示例

🌵过滤出 22 号端口
[root@shawn home]#netstat -an | grep :22
tcp   0   0 0.0.0.0:22         0.0.0.0:*              LISTEN     
tcp   0  52 192.168.12.178:22  192.168.12.179:57156  ESTABLISHED
tcp6  0   0 :::22 

🌵过滤出 25 号端口
[root@shawn home]#netstat -an | grep :25
tcp   0  0 127.0.0.1:25    0.0.0.0:*        LISTEN     
tcp6  0  0 ::1:25          :::*             LISTEN  

🌵查看你进程开打的文件,打开文件的进程,进程打开的端口(TCP、UDP)(了解)
[root@shawn home]#lsof -i:22
COMMAND  PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
sshd    1201 root    3u  IPv4  20467      0t0  TCP *:ssh (LISTEN)
sshd    1201 root    4u  IPv6  20476      0t0  TCP *:ssh (LISTEN)
sshd    1289 root    3u  IPv4  21134      0t0  TCP shawn:ssh->192.168.12.179:57156 (ESTABLISHED)

五.proc 文件系统

1. 什么是 proc 文件系统

  • proc 文件系统是一个虚拟文件系统,它只存在内存当中,而不占用外存空间
它以文件系统的方式为访问系统内核数据的操作提供接口
用户和应用程序可以通过 proc 得到系统的信息,并可以改变内核的某些参数
由于系统的信息,如进程,是动态改变的
所以用户或应用程序读取 proc 文件时
proc 文件系统是动态从系统内核读出所需信息并提交的

2. 查看 CPU 信息

  • CPU 信息文件: /proc/cpuinfo
🌵可以用文件查看命令查看(more,less,cat.....)
[root@shawn ~]#less /proc/meminfo

🌵过滤查看逻辑 "CPU" 个数
[root@shawn ~]#grep "processor" /proc/cpuinfo
processor   : 0

🌵过滤查看物理 "CPU" 个数  
[root@shawn ~]#grep "physical id" !$
grep "physical id" /proc/cpuinfo
physical id : 0

🌵"cpu" 核数
[root@shawn ~]#grep "cpu cores" !$
grep "cpu cores" /proc/cpuinfo
cpu cores   : 1

3. 查看内存信息

  • 内存信息文件: /proc/meminfo
🌵可以用文件查看命令查看(more,less,cat.....)
[root@shawn ~]#less /proc/meminfo
[root@shawn ~]#lscpu

🌵查看内存使用情况(单位:b,k,m,g)(buffer/cache 分开查看)
[root@shawn ~]#free
         total      used     free      shared  buff/cache   available
Mem:     995684    125424    544644    6984    325616      714228
Swap:    2464760     776     2463984
[root@shawn ~]#free -m
         total     used    free   shared  buff/cache   available
Mem:     972       114     805      6        53         758
Swap:    2406        0     2406
[root@shawn ~]#free -wm
        total    used   free    shared   buffers   cache   available
Mem:     972     114     805      6        0        53      758
Swap:    2406     0      2406

🌵将 "buff" 缓冲区内容写入硬盘(通常多敲几遍)
[root@shawn ~]#sync
[root@shawn ~]#sync

🌵释放 "buff/cache" 空间
[root@shawn ~]#free
       total     used    free    shared  buff/cache   available
Mem:   995684    125424  544644   6984    325616      714228
Swap:  2464760   776     2463984
[root@shawn ~]#echo 3 > /proc/sys/vm/drop_caches 
[root@shawn ~]#free
       total      used      free    shared  buff/cache  available
Mem:   995684      112056   845300   6988   38328       789576
Swap:  2464760     776     2463984
🌵使用 "echo > 3" 将 "buff/cache" 的内存空间释放, 前后对比可发现 "free" 变大了

4. 内核启动参数

  • 文件:/proc/cmdline
🌵可以用文件查看命令查看(more,less,cat.....)
[root@shawn ~]#less /proc/cmdline
BOOT_IMAGE=/vmlinuz-3.10.0-1127.19.1.el7.x86_64 root=UUID=74cf4c48-4939-4398-a99a-65fb8e830a8d ro rhgb quiet net.ifnames=32 biosdevname=32 LANG=zh_CN.UTF-8

🌵显示 "uptime", 显示结果与 "top" 命令显示的首行一样
[root@shawn ~]#uptime
 16:43:57 up  4:26,  1 user,  load average: 0.00, 0.01, 0.05

5. 卸载与挂载 /proc

  • 卸载
🌵一般需要使用 "-l" 强制卸载
[root@shawn ~]#umount /proc
umount: /proc:目标忙。(有些情况下通过 lsof(8) 或 fuser(1) 可以
         找到有关使用该设备的进程的有用信息)
[root@shawn ~]#umount /proc -l

🌵卸载后以下命令不可用
"free", "uptime", "lscpu", "toop"
[root@shawn ~]#free
Error: /proc must be mounted  #表示命令不可用了
  To mount /proc at boot you need an /etc/fstab line like:
      proc   /proc   proc    defaults
  In the meantime, run "mount proc /proc -t proc"
[root@shawn ~]#uptime
Error: /proc must be mounted
  To mount /proc at boot you need an /etc/fstab line like:
      proc   /proc   proc    defaults
  In the meantime, run "mount proc /proc -t proc"
.............
........
...
  • 重新挂载
🌵重新挂载后命令可用
[root@shawn ~]#mount -t proc proc /proc
[root@shawn ~]#free
       total    used    free   shared  buff/cache   available
Mem:   995684   117704  814036   6992    63944      771124
Swap:  2464760   776     2463984

 "-t proc" : 指定文件系统类型
 "proc" : 文件系统, 虚拟文件系统
 "/proc" : 挂载点
# du -sh * 查看当前目录下各个文件及目录占用空间大小
# du -sh [目录] 查看目录目录下各个文件及目录占用空间大小

六. 管理后台进程

1.jobs显示当前终端里的后台任务

2.bg让作业在后台运行

3.fg将作业调回前台

4. 示例

🌵首先开启三个任务,"[ ]" 里面的是作业编号
[root@shawn home]#sleep 5000 & 
[4] 5300
[root@shawn home]#sleep 4000 &
[5] 5301
[root@shawn home]#sleep 3000 &
[6] 5302

🌵使用 "jobs" 命令查看当前终端后台任务(其他终端看不到)
[root@shawn home]#jobs
[4]   运行中               sleep 5000 &
[5]-  运行中               sleep 4000 &
[6]+  运行中               sleep 3000 &

🌵使用 "fg" 命令将作业 "4" 调回前台运行, 然后 "Ctrl + z" 将其暂停并挂起后台
[root@shawn home]#fg %4
sleep 5000
^Z   #这里是 "Ctrl + z"
[4]+  已停止               sleep 5000
[root@shawn home]#jobs
[4]+  已停止               sleep 5000     #可以发现已经停止了
[5]   运行中               sleep 4000 &
[6]-  运行中               sleep 3000 &

🌵使用 "bg" 将作业 "4" 运行在后台
[root@shawn home]#bg %4
[4]+ sleep 5000 &
[root@shawn home]#jobs
[4]   运行中               sleep 5000 &   #可以发现已经在后台运行了
[5]-  运行中               sleep 4000 &
[6]+  运行中               sleep 3000 &

🌵使用 "kill" 命令杀掉作业
[root@shawn home]#kill %4
[root@shawn home]#jobs
[4]   已终止               sleep 5000     #可以看到作业已经终止
[5]-  运行中               sleep 4000 &
[6]+  运行中               sleep 3000 &

七. 管道

1. 什么是管道

  • 主要用来连接左右两个命令, 符号 "|"

  • 将左侧命令的标准输出, 传给右侧命令的标准输入

  • 注意: 无法传递标准错误输出至后者命令

  • 用法:command1 | command2 | command3 ......

2. 管道示意图

25 HUP 信号, 僵尸进程与孤儿进程

  • 示例
🌵过滤网卡 init 
[root@shawn ~]#ifconfig | grep "inet"
        inet 192.168.12.178  netmask 255.255.255.0  broadcast 192.168.12.255
        inet6 fe80::20c:29ff:fe3e:456a  prefixlen 64  scopeid 0x20<link>
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
[root@shawn ~]#ifconfig | grep "inet" | awk '{print $2}'
192.168.12.178
fe80::20c:29ff:fe3e:456a
127.0.0.1
::1

3. 管道中的 tee 技术

  • 示意图

25 HUP 信号, 僵尸进程与孤儿进程

  • 示例

25 HUP 信号, 僵尸进程与孤儿进程

4.xargs 参数传递

  • 让不支持管道的命令也可以使用管道内的内容
find /root -name "song*" | xargs rm -rvf   #删除管道里的内容
find /root -name "song*" | xargs -I {} cp -rf {} /tmp
find /root -name "song*" | xargs -I {} mv {} /tmp
find /root -name "song*" | xargs -I {} chmod 777 {} #修改找到的文件的权限等级
正文完
 
shawn
版权声明:本站原创文章,由 shawn 2023-06-16发表,共计7981字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
评论(没有评论)