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
原文地址:https://www.cnblogs.com/syy1757528181/p/13603831.html