zoukankan      html  css  js  c++  java
  • 🍖HUP信号,僵尸进程与孤儿进程

    一.关于HUP信号

    1.什么是HUP信号

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

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

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

    • 解决方法:

      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然后查看进程信息

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

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

    发现对 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 &" 进程, 把它当做子进程
    • 然后在另一个虚拟终端查看这两个进程信息

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

    • 图示

    三.僵尸进程

    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.管道示意图

    • 示例
    过滤网卡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 技术

    • 示意图

    • 示例

    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 {} #修改找到的文件的权限等级
    
  • 相关阅读:
    stl的erase()陷阱--迭代器失效总结
    .NET Framework 概述
    C#在代码中编写输出debug信息-类Debug的使用
    C# 开发的windows服务 不能调试——讨论整理
    C#开发windows服务如何调试——资料整理
    iis深入学习资源
    网站因权限问题报错
    数据库建表经验总结——建表现象—sql查询疑惑
    java8大基本类型
    存储过程中的事务
  • 原文地址:https://www.cnblogs.com/songhaixing/p/13938908.html
Copyright © 2011-2022 走看看