• linux信号


    linux信号

    一、现象描述:
    1.当运行shell脚本时,如果按下Ctrl+c 或Ctrl+x(x为其他字符),程序会终止运行。
    2.当不希望shell在运行时被终止,则可以使用屏蔽信号手段,让程序忽略用户输入的信号指令,从而继续运行shell程序。
    二、信号含义:
    信号是由一个整数构成的异步消息,它可以由某个进程发给其他进程,也可以在用户按下特定按键发生某种异常事件时,由系统发给某个进程。

    1.Linux重要信号
    kill -l
    HUP(1)  挂起,通常因终端掉线或用户退出而引发
    INT(2)  中断,通常因为按ctrl + c组合键而引发
    QUIT(3) 退出,通常因为按ctrl +  组合键而引发
    ABRT(6)  中止 , 通常因为某些严重的执行错误而引发
    KILL(9)  杀死 , 强制杀死
    ALRM(14) 报警 , 通常用来处理超时
    TERM(15) 终止 ,通常在系统关机时发送,正常退出
    TSTP(20) 停止进程的运行,但该信号可以被处理和忽略,通常是Ctrl + z键而引发
    
    注:
        shell脚本中可以用数字来代表信号,也可以用信号的名字代表信号,也可以用组合键代表信号
    	不是所有的信号都能被trap捕捉(比如 kill -9),trap只能捕捉常见的信号
    	收到信号的是进程、所有进程
    	终端也可以叫做会话
    	父进程死亡,子进程将会成为孤儿进程,被systemd进程(pid=1)收留(父进程被杀)
    	关闭终端,发送HUP信号,systemd包括其子进程被中断
    
    2.trap命令
    trap命令:
        1.用于在接受到信号后将要采取的行动
        2.常用于在脚本程序被中断时完成清理工作,或者屏蔽用户非法使用的某些信号
    注:
        使用信号名时需要省略前缀"SIG"
    用法:
        trap command signal
        signal是接受到的信号 , command是接收到信号后应该采取的行动
        trap "命令;命令" 信号名      或者 trap "命令;命令" 信号编号
    

    例一:

    处理单个信号:
    [centos@mycentos ~]$ trap "" 2  #若执行动作为空,则可以用来屏蔽与数字对应的Ctrl+c信号
    [centos@mycentos ~]$ trap ":" 2 #此处恢复Ctrl + c 的信号 
    [centos@mycentos ~]$ ^C    #已恢复
    

    例二:

    同时处理多个信号:
    [centos@mycentos ~]$ trap "" 1 2 3 20 #<==执行这些数字信号,什么都不做,即屏蔽这些信号
    [centos@mycentos ~]$ trap ":" 1 2 3 20 #<==执行这些信号,恢复对应的功能
    [centos@mycentos ~]$ ^C
    [centos@mycentos ~]$ trap "" HUP INT QUIT TSTP #<==执行这些名称信号,什么都不做,即屏蔽这些信号
    [centos@mycentos ~]$ trap ":" HUP INT QUIT TSTP #<==执行这些名称信号,恢复对应的功能
    [centos@mycentos ~]$ ^C
    [centos@mycentos ~]$ trap "" `echo {1..64}` #<==屏蔽1-64所有的数字信号
    

    实战一:
    开发脚本实现触发信号后清理文件功能(信号触发后就会执行将新建的文件删除命令)

    #!/bin/bash
    #Auther:itboy
    #Time:2018-11-20 10:09:42
    #Name:3.sh
    #Version:V1.0
    #Description:this is a test script.
    
    #<==捕获ctrl+c 键后即执行find删除命令,后退出脚本
    trap "find /tmp -type f -name "old_*" | xargs rm -f && exit" INT
    
    while true
    do
        touch /tmp/old_$(date +%F-%T) #<==在/tmp创建文件
        sleep 5     #<==休息3秒
        ls -la /tmp/old*    #<==查看文件创建情况
    done
    

    实战二:
    开发脚本,练习QUIT、TSTP、INT

    #!/bin/sh
    #捕获ctrl+c信号时,执行echo命令
    trap 'echo "you are typing ctrl-c ,sorry,script will not terminate"' INT
    #捕获Ctrl+信号,执行echo
    trap 'echo "you are typing ctrl- ,sorry,script will not terminate"' QUIT
    #捕获ctrl+z信号,就会执行echo命令 (实测此处没有执行echo命令,进程异常)
    trap 'echo "you are typing ctrl-z ,sorry,script will not terminate"' TSTP
    while true
    do
        echo "now , test signal $(date)"
        sleep 5
    done
    

    效果如下

    [root@mycentos ~]# sh 2.sh 
    now , test signal Tue Nov 20 11:02:06 CST 2018
    ^Cyou are typing ctrl-c ,sorry,script will not terminate  #按下ctrl+c执行
    now , test signal Tue Nov 20 11:02:11 CST 2018
    now , test signal Tue Nov 20 11:02:16 CST 2018
    now , test signal Tue Nov 20 11:02:21 CST 2018
    ^Quit (core dumped)
    you are typing ctrl- ,sorry,script will not terminate #按下ctrl+执行
    now , test signal Tue Nov 20 11:02:25 CST 2018
    now , test signal Tue Nov 20 11:02:30 CST 2018
    ^Z^Z                            #按下ctrl +z 键没有打印提示,但是程序停止运行了
    

    实战三

    实现红绿灯

    #!/bin/bash
    
    trap "" INT QUIT HUP TERM TSTP
    clear
    n=0
    
    while :
    do
        [ $n -eq 0 ] && n=1 || n=0    
    
        if [ $n -eq 1 ];then
            echo -e "33[31m 红灯亮 33[0m"
        else
            echo -e "33[32m 绿灯亮 33[0m"
        fi
        
        sleep 0.5
        clear
    done 
    

    实现红黄绿

    #!/bin/bash
    
    #trap "" INT QUIT HUP TERM TSTP
    
    clear
    while :
    do
        for i in 0 1 2
        do
            case $i in
            0)
                echo -e "33[31m 红灯亮 33[0m"
                ;;
            1)
                echo -e "33[33m 黄灯亮 33[0m"
                ;;
            2)
                echo -e "33[32m 绿灯亮 33[0m"
            esac
            sleep 0.5
            clear
        done
    done
    

    进程脱离当前终端

    一父进程

    父进程自杀

    [root@hass-11 ~]# tty
    /dev/pts/3
    [root@hass-11 ~]# sh 1.sh &
    [root@hass-11 ~]# ps -ef|grep 1.sh
    root      92154  79953  0 10:44 pts/0    00:00:00 sh 1.sh
    root      92221  79953  0 10:44 pts/0    00:00:00 grep --color=auto 1.sh
    [root@hass-11 ~]# kill 79953
    [root@hass-11 ~]# ps -ef|grep 1.sh
    root      92154  79953  0 10:44 pts/0    00:00:00 sh 1.sh
    root      92260  79953  0 10:45 pts/0    00:00:00 grep --color=auto 1.sh
    [root@hass-11 ~]# kill -9 79953
    重新连接该终端,发现进程退出
    
    #该命令的过程有两个
    	1.父进程自杀
    	2.子进程被杀
    

    父进程被杀

    #窗口1
    [root@hass-11 ~]# tty
    /dev/pts/3
    [root@hass-11 ~]# sh 1.sh &
    [root@hass-11 ~]# ps -ef|grep 1.sh
    root      92427  92356  0 10:46 pts/0    00:00:00 sh 1.sh
    root      92472  92356  0 10:46 pts/0    00:00:00 grep --color=auto 1.sh
    [root@hass-11 ~]# echo $$
    92356
    
    #窗口2
    [root@hass-11 ~]# tty
    /dev/pts/1
    [root@hass-11 ~]# ps -ef|grep 1.sh
    root      92427  92356  0 10:46 pts/0    00:00:00 sh 1.sh
    root      92558  89686  0 10:47 pts/1    00:00:00 grep --color=auto 1.sh
    [root@hass-11 ~]# kill -9 92356
    [root@hass-11 ~]# ps -ef|grep 1.sh		#杀死父进程,子进程在该终端继续存活
    root      92427      1  0 10:46 ?        00:00:00 sh 1.sh
    root      92596  89686  0 10:47 pts/1    00:00:00 grep --color=auto 1.sh
    
    #此方法可以让进程脱离终端限制
    #该方法原理与nohup一样
    

    二nohup

    #窗口1
    [root@hass-11 ~]# echo $$	#查看当前进程的PID
    98947
    [root@hass-11 ~]# nohup ping www.baidu.com &
    [1] 114856
    [root@hass-11 ~]# ps -ef|grep [p]ing
    root     114856  98947  0 13:37 pts/2    00:00:00 ping www.baidu.com
    [root@hass-11 ~]# exit
    
    #窗口2
    [root@hass-11 ~]# echo $$
    89686
    [root@hass-11 ~]# ps -ef|grep [p]ing
    root     114856      1  0 13:37 ?        00:00:00 ping www.baidu.com
    
    #nohup的原理是,使要运行的进程的父进程是systemd
    

    三setsid

    #窗口1
    [root@hass-11 ~]# setsid ping www.baidu.com &
    [root@hass-11 ~]# exit
    
    #窗口2
    [root@hass-11 ~]# ps -ef|grep [p]ing
    root     115312      1  0 13:40 ?        00:00:00 ping www.baidu.com
    
    #setsid的原理是,使要运行的进程的父进程是systemd
    

    四 ( &)

    #窗口1 
    [root@hass-11 ~]# (ping www.baidu.com &)	#必须加 & 符号
    [root@hass-11 ~]# exit
    
    #窗口2
    [root@hass-11 ~]# ps -ef|grep [p]ing
    root     115794      1  0 13:44 ?        00:00:00 ping www.baidu.com
    
    #原理是开启一个子进程,使要运行的进程的父进程是systemd
    
  • 相关阅读:
    database join
    图像超分辨率重建
    信号处理
    将博客搬至CSDN
    Openstack
    nginx的优化
    CentOS系统的优化
    zabbix服务端客户端部署
    MySQL优化必须调整的10项配置
    TCP三次握手
  • 原文地址:https://www.cnblogs.com/syy1757528181/p/13603831.html
Copyright © 2020-2023  润新知