📹 进程管理(二)

一、关于HUP信号

要了解linux的HUP信号,需从hangup说起

在Unix的早期版本中,每个终端都会通过modem和系统通讯

当用户logout时,modem就会挂断(hang up)电话

同理,当modem断开连接时,就会给终端发送hang up 信号来通知其关闭所有子进程

综上所得,当用户注销(logout)或者网络断开或者终端关闭(注意:一定是终端关闭,不是单纯的exit退出时)终端都会收候到linux HUP信号(hangup)信号,然后终端在结束前会关闭有子进程。

如果想让进程在后台一直运行,不要因为用户注销(logout)或者网络断开或者终端关闭而被一起干掉,有两种解决方案

  • 方案一:让进程忽略linux HUP信号
  • 方案二:让进程运行在新的会话里,从而成为不属于此终端进程,就不会在当前终端挂掉的情况下一起被带走

1.nohup命令

 针对方案一;可以使用nohup命令,nohup的用途就是让提交的命令忽略hangup信号,该命令通常与&符号一起使用

nohup的使用是十分方便的,只需要在要处理的命令前加上 nohup即可,但是nohup命令命令会从终端解除进程的关联,进程会丢掉STDOUT,STDERR的链接。标准输出和标准错误缺省会被重定向到nohup.out文件中。一般在结尾加上"&"来将命令同时放入后台运行,也可以用">filename 2>&1"来更改缺省的重定向文件名

2.setsid命令

针对方案1,我们还可以用setsid命令实现,原理与3.1是一样的,setid是直接将进程的父pid设置成1,即让运行的进程归属于init的子进程,那么除非init结束,该子进程才会结束,当前进程所在的终端结束后并不会影响进程的运行

# 1、在终端2中执行命令
[root ~]# setsid ping www.baidu.com # 也可以在后面加&符号

# 2、关闭终端2

# 3、在终端1中查看
[root ~]# ps -ef |grep [p]ing
root 102335 1 0 17:53 ? 00:00:00 ping www.baidu.com

3.在子shell中提交任务

# 1、在终端2中执行命令
[root ~]# (ping www.baidu.com &) # 提交的作业并不在作业列表中

# 2、关闭终端2

# 3、在终端1中查看
[root ~]# ps -ef |grep [p]ing
root 102361 1 0 17:55 ? 00:00:00 ping www.baidu.com
 
可以看到新提交的进程的父ID(PPID)为(init进程的PID),并不是当前终端的进程id。因此并不属于当前终端的子进程,从而也就不会受到当前终端的linux HUP信号影响了

4.screen命令

# 1.运行命令
方式一:开启一个窗口名,也可以不指定
[root ~]# screen -S tom_dsb 
'''
Screen将创建一个执行shell的全窗口,执行任意shell程序,在该窗口中输入exit则退出该窗口,如果此时,这是该screen会话的唯一窗口,该screen会话退出,否则screen自动切换到提前一个窗口
'''
 方式二:screen命令后跟要执行的程序
[root ~]# screen vim test.txt
'''
Screen创建一个执行vim test.txt的单窗口会话,退出vim将退出该窗口/会话
'''
# 原理分析
screen程序会帮我们管理运行的命令,退出screen,命令还会继续运行,若关闭screen所在的终端,则screen程序的ppid变为1,所以screen不会死掉,对应着它帮我们管理的命令也不会退出


# 4.重新连接会话
在终端1中运行
[root~]# screen
[root ~]# n=1;while true;do echo $n;sleep 1;((n++));done
[root ~]# 按下ctrl+a,然后再按下ctrl+d,注意连贯,受别哆嗦
[root ~]#此时可以关闭整个终端,运行的程序并不会结束 

打开一个新的终端
[root ~]# screen -ls
There is a screen on:
109125.pts-0.egon (Detached)
1 Socket in /var/run/screen/S-root.
[root ~]# screen -r 109125 # 会继续运行
 

注:如果开始就使用了screen -S  xxx指定了名字,那么我们其实可以直接screen -r xxx,就不需要去找进程id了

screen常用参数选项

常用命令选项:
-c file ֵ                 使用配置文件file,而不使用默认的$HOME/.screenrc
-d|-D [pid.tty.host]     不开启新的screen会话,而是断开其他正在运行的screen会话
-h num                   指定历史回滚缓冲区大小为num行
-list|-ls                列出现有的screenտ会话,格式为pid.tty.host
-d -m                    启动一个开始就处于断开模式的会话
-r [pid.tty.host]        重新连接一个断开的会话
-S sessionname           创建screen会话时为会话指定一个名字
-v                       显示screen版本信息
-wipe [match]            同 -list,但删掉那些无法连接的会话
-x                       会话共享演示

查看网络状态netstat命令

[root ~]# netstat -tnlp # 查看正在监听的,且使用tcp协议的进程
-t tcp协议
-u udp协议
-l listen
-p PID/Program name
-n 不反解,不将IP地址解析为主机名,不讲端口号解析成协议名(80------->http)


示例
[root ~]# netstat -an |grep :22
[root ~]# netstat -an |grep :80
[root ~]# lsof -i:22

二、proc文件系统

  • [root@localhost ~]# du -sh /proc
      cpu:/proc/cpuinfo
[root@localhost ~]# grep "processor" /proc/cpuinfo # 逻辑cpu个数
processor : 0
[root@localhost ~]# grep "physical id" /proc/cpuinfo # 物理cpu个数
[root@localhost ~]# grep "cpu cores" /proc/cpuinfo # cpu核数

cpu cores : 1
 
[root@localhost ~]# cat /proc/cpuinfo 
==flags
lm (64位)
vmx 支持虚拟化 Intel
svm 支持虚拟化 AMD
[root@localhost ~]# egrep --color 'lm|vmx|svm' /proc/cpuinfo 
[root@localhost ~]# lscpu

内存:/proc/meminfo

查看内存
[root ~]# less /proc/meminfo
[root ~]# free -wm
             total     used     free     shared     buffers 
cache available
Mem:     1980     192     1713         9            0 
74 1671    
Swap:    1023         0     1023
[root ~]# free -m
             total     used     free     shared     buff/cache 
available
Mem:     1980     192     1713         9             74 
1672
Swap:     1023         0    1023                            

内核启动参数:/proc/cmdline

[root@localhost ~]# cat /proc/cmdline
BOOT_IMAGE=/vmlinuz-3.10.0-1127.13.1.el7.x86_64 root=UUID=84b5cfa6-b0dc-4d7aa8fd-0302f0eb2f04 ro rhgb quiet LANG=zh_CN.UTF-8

[root@localhost ~]# uptime
 17:42:40 up 1 day, 1:33, 2 users, load average: 0.00, 0.01, 0.05
        注:当卸载/proc后
[root@localhost ~]# umount /proc -l
# 下述命令都不可用
free -m
uptime
lscpu
toop


重新挂载
[root@localhost ~]# mount -t proc proc /proc/
-t proc    指定文件系统的类型
proc       文件系统,虚拟文件系统
/proc      挂载点

三、管理后台进程

[root@localhost ~]# sleep 5000 &  #运行程序(时),让其在后台执行
[1] 31143
[root@localhost ~]# sleep 4000 # ^z,将前台的程序挂起(暂停)到后台
[root@localhost ~]# jobs # 中括号内的编号就是作业编号, %1代表作业1
[1]- 运行中                sleep 5000 &
[2]+ 已停止                sleep 4000
[root@localhost ~]# bg %2 # 让作业2在后台运行
  [2]+ sleep 4000 &
  [root@localhost ~]# fg %1 # 将作业1调回到前台
  [root@localhost ~]# jobs
  [2]+ 运行中              sleep 4000 &
  [root@localhost ~]# kill %2
nohup
加在一个命令的最前面,表示不挂断的运行命令

 四、管道

1、什么是管道

管道用于进程间通信

[root@localhost ~]# ps aux |grep "httpd"
[root@localhost ~]# yum list |grep nginx

详细的说,管道操作符号“|”主要用来链接另两个命令,将左侧的命令的标准输出,交给右侧命令的标准输入

PS:无法专递标准错误输出置后者命令

格式:cmd1 | cmd2 [...|cmdn]

 2、管道流程图

 3、管道应用示例

例1:统计当前/etc/passwd中用户使用的shell类型
[root@localhost ~]# awk -F: '{print $7}' /etc/passwd | sort |uniq -c
 2 /bin/bash
 1 /bin/sync
 1 /sbin/halt
 40 /sbin/nologin
 1 /sbin/shutdown



例2:统计网站的访问情况
[root@localhost ~]# netstat -an |grep :80 |awk -F":" '{print $8}'|sort |uniq -
c 


例3:答应当前所有IP
[root@localhost ~]# ip addr |grep 'inet ' |awk '{print $2}' |awk -F"/" '{print
$1}'
127.0.0.1
192.168.12.21
192.168.122.1
ֺ

例4:打印根分区已用空间的百分比
[root@localhost ~]# df -P|grep '/$' |awk '{print $5}'|awk -F"%" '{print $1}'
50
ֺ


例5:ip top 10
#思路:打印所有访问过来的IP |排序|去重|倒叙排列|取前10
[root ~]# awk '{print $1}' access.log |sort |uniq -c |sort -rn|head
12049 58.220.223.62
10856 112.64.171.98
1982 114.83.184.139
1662 117.136.66.10
1318 115.29.245.13
961 223.104.5.197
957 116.216.0.60
939 180.111.48.14
871 223.104.5.202
869 223.104.4.139

4、管道中的tree技术

 重定向与tee他们在使用过程中有什么区别

[root ~]# date > date.txt #直接将内容写入date.txt文件中
[root ~]# date |tee date.txt #命令执行会输出至屏幕,但会同时保存一份至date.txt文件中
5、xargs参数传递,主要让一些不支持管道的命令可以使用管道技术
[root ~]# which cat|xargs ls -l
[root ~]# ls |xargs rm -fv
[root ~]# ls |xargs cp -rvt /tmp/ -౲-> ls | xargs -I {} cp -rv {} /tmp/
[root ~]# ls |xargs mv -t /tmp/ -౲-> ls | xargs -I {} mv {} /tmp五、 

五、僵尸进程与孤儿进程

1、什么是僵尸进程

僵尸进程是当子进程比父进程先结束,而父进程又没有回收子进程,释放子进程占用的资源,此时子进程将成为一个僵尸进程。如果父进程先退出 ,子进程被init接管,子进程退出后init会回收其占用的相关资源

2、僵尸进程残存的数据是否需要回收

需要回收,僵进程毕竟只是linux系统的机制,为父进程准备数据,置于回收操作,应该是父进程觉得自己无需查看僵尸进程的数据,留着也无用,所以就会发起wait /waitpid来通知linux操作系统来清理掉僵尸进程

3、僵尸进程是怎么出现的

1、linux系统自带一些优秀的开源软件,这些软件在开启子进程时,父进程内部都会调用wait/waitpid来通知操作系统及时回收僵尸进程,所以一般看不到

2、一些资深的程序员开发应用程序时,他们知道父进程要对子进程负责,会考虑及时回收问题,有时候可能会遇见[root ~]# ps aux | grep [Z]+

3、一些技术较差的程序员并不知道僵尸进程,没有考虑回收问题,子进程会不停产生,父进程也不结束,所以系统中就会堆积许多的僵尸进程,占用大量pid,影响正常程序的启动

4、如何清理僵尸进程

1、通知父进程,调用wait/waitpid来清理子进程 kill -CHLD  父进程ID

2、直接杀死父进程,僵尸进程就会被超级进程(init或systemd)接管,超级系统会调用wait/waitpid来让操作系统清理僵尸进程

示例:

=====================窗口1======================
[root ~]# cat test.py 
#coding:utf-8
from multiprocessing import Process
import os
import time

def task():
           print("father--->%s son--->%s" %(os.getppid(),os.getpid()))

if __name__ == "__main__":
     p1=Process(target=task)
     p2=Process(target=task)
     p3=Process(target=task)
     p1.start()
     p2.start()
     p3.start()
     print("main--->%s" %os.getpid())
     time.sleep(10000)
[root ~]# python test.py &
[5] 104481
[root ~]# main--->104481
father--->104481 son--->104482
father--->104481 son--->104483
father--->104481 son--->104484



=====================窗口2======================
[root ~]# ps aux |grep Z
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 104482 0.0 0.0 0 0 pts/2 Z 18:24 0:00 [python]
<defunct>
root 104483 0.0 0.0 0 0 pts/2 Z 18:24 0:00 [python]
<defunct>
root 104484 0.0 0.0 0 0 pts/2 Z 18:24 0:00 [python]
<defunct>
root 104488 0.0 0.0 112828 960 pts/4 R+ 18:24 0:00 grep --
color=auto Z

5、孤儿进程

父进程先结束了运行,而父进程产生的子进程依然在运行,这就是所谓的孤儿进程,孤儿进程会被超级进程收养,并由超级进程对他们完成状态收集工作

测试
import os
import sys
import time
pid = os.getpid()
ppid = os.getppid()
print 'im father', 'pid', pid, 'ppid', ppid
pid = os.fork()
#执行pid=os.fork() 则会生成一个子进程
#返回值pidํ有两种值:
#         如果返回的pid值为=0,表示在子进程当中
#         如果返回值pid值为>0,表示在父进程当中
if pid > 0:
     print 'father died..'
     sys.exit(0)

#保证主线程序退出完毕
time.sleep(1)
print 'im child', os.getpid(), os.getppid()

执行文件,输出结果
im father pid 32515 ppid 32015
father died..
im child 32516 1

此时,子进程已被超级进程接收,只存在孤儿进程,周期结束自然会被清理
原文地址:https://www.cnblogs.com/ChuangShi-HolySpirit/p/13934118.html