1、信号知识
1.1、信号介绍
运行Shell脚本程序时,如果按下快捷键Ctrl+c或Ctrl+x(x为其他字符),程序就会立刻终止运行。
在有些情况下,我们并不希望Shell脚本在运行时被信号中断,此时就可以使用屏蔽信号手段,让程序忽略用户输入的信号指令,从而继续运行Shell脚本程序。
简单地说,Linux的信号是由一个整数构成的异步消息,它可以由某个进程发给其他的进程,也可以在用户按下特定键发生某种异常事件时,由系统发给某个进程。
1.2、信号列表
在Linux下和信号相关的常见命令为kill及trap命令,本章将重点讲解如何使用trap命令,以及如何利用trap控制的跳板机脚本来使用信号。
执行kill -l或trap -l命令,可以列出系统支持的各种信号,多达64个,如图所示。

下面将对企业实战中Linux系统的重要信号进行说明,见表。

在使用信号名时需要省略SIG前缀。
通常需要忽略的信号包括HUP、INT、QUIT、TSTP、TERM等,对应的信号编号分别为1、2、3、20、15。Shell脚本中既可以用数字来代表信号,也可以使用信号的名字来代表信号,如果读者想要了解关于信号的更多知识,可以加本书的QQ交流群(本书前言中有提供),群里有详细的文档说明。
2、使用trap控制信号
trap命令用于指定在接收到信号后将要采取的行动,信号的相关说明前面已经提到过。trap命令的一种常见用途是在脚本程序被中断时完成清理工作,或者屏蔽用户非法使用的某些信号。在使用信号名时需要省略SIG前缀。可以在命令提示符下输入命令trap -l来查看信号的编号及其关联的名称。
trap命令的参数分为两部分,前一部分是接收到指定信号时将要采取的行动,后一部分是要处理的信号名。
trap命令的使用语法如下:
trap command signal
signal是指接收到的信号,command是指接收到该信号应采取的行动。也就是:
trap ’命令;命令’ 信号编号
或
trap ’命令;命令’ 信号名
范例:测试trap命令捕获Ctrl+c信号。
[root@oldboy ~]# trap 'echo oldboy' 2 #<==当执行此命令时,按Ctrl+c键,就会执行echo命令,这里结尾的2就是Ctrl+c键对应的数字信号。
[root@oldboy ~]# ^Coldboy #<==按Ctrl+c键后调用echo命令输出结果。
[root@oldboy ~]# ^Coldboy #<==按Ctrl+c键后调用echo命令输出结果。
[root@oldboy ~]# trap "echo oldgirl" INT #<==当执行此命令时,按Ctrl+c键,就会执行echo命令,这里结尾的INT就是Ctrl+c键对应的信号名称。
[root@oldboy ~]# ^Coldgirl #<==按Ctrl+c键后调用echo命令输出结果。
[root@oldboy ~]# ^Coldgirl #<==按Ctrl+c键后调用echo命令输出结果。
用stty -a可以列出中断信号与键盘的对应信息,如下:
[root@oldboy ~]# stty -a
speed 38400 baud; rows 20; columns 103; line = 0;
intr = ^C; quit = ^\; erase = ^? ; kill = ^U; eof = ^D; eol = <undef>; eol2 =
<undef>; swtch = <undef>;
start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R; werase = ^W; lnext = ^V;
flush = ^O; min = 1; time = 0;
-parenb -parodd cs8 -hupcl -cstopb cread -clocal -crtscts -cdtrdsr
-ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl ixon
-ixoff -iuclc -ixany -imaxbel
-iutf8 opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0
bs0 vt0 ff0
isig icanon iexten echo echoe echok -echonl -noflsh -xcase -tostop -echoprt
echoctl echoke
范例:测试按下Ctrl+c组合键而引发的INT(2)信号。
[root@oldboy ~]# trap "" 2 #<==执行动作处为空,此命令可以用来屏蔽与数字对应的Ctrl+c信号。
[root@oldboy ~]# #<==此时执行Ctrl+c键无任何反应。
[root@oldboy ~]# trap ":" 2 #<==恢复Ctrl+c信号。
[root@oldboy ~]# #<==此时可以执行Ctrl+c了。
[root@oldboy ~]# trap "echo -n 'you are typing ctrl+c'" 2
[root@oldboy ~]# ^Cyou are typing ctrl+c
[root@oldboy ~]# ^Cyou are typing ctrl+c
[root@oldboy ~]# ^Cyou are typing ctrl+c
[root@oldboy ~]# ^Cyou are typing ctrl+c
范例:同时处理多个信号。
执行任何一个对应信号的事件时,都会执行前面对应的动作,因为动作为空,所以执行后没有任何反应。
[root@oldboy ~]# trap "" 1 2 3 20 15 #<==执行这些数字信号,什么都不做。
[root@oldboy ~]# trap ":" 1 2 3 20 15 #<==执行这些数字信号,恢复对应功能。
[root@oldboy ~]# ^C
[root@oldboy ~]# trap "" HUP INT QUIT TSTP TERM #<==执行这些名称信号,什么都不做。
[root@oldboy ~]# trap ":" HUP INT QUIT TSTP TERM #<==执行这些名称信号,恢复对应功能。
[root@oldboy ~]# trap "" `echo {1..64}` #<==屏蔽1-64的所有数字信号。
3、Linux信号及trap命令的生产应用案例
范例:开发脚本实现触发信号后清理文件功能。
脚本如下:
[root@oldboy scripts]# cat 17_4_1.sh
#! /bin/bash
#Author:oldboy training
trap "find /tmp -type f -name "oldboy_*"|xargs rm -f && exit" INT
#<==捕获Ctrl+c键后即执行find删除命令。
while true
do
touch /tmp/oldboy_$(date +%F-%H-%M-%S) #<==在/tmp下创建文件。
sleep 3 #<==休息3秒。
ls -l /tmp/oldboy* #<==查看文件创建的情况。
done
[root@oldboy scripts]# sh 17_4_1.sh #<==执行脚本后,很快就会在/tmp下创建很多文件。
-rw-r--r-- 1 root root 0 9月 22 13:41 /tmp/oldboy_2016-09-22-13-41-08
-rw-r--r-- 1 root root 0 9月 22 13:41 /tmp/oldboy_2016-09-22-13-41-08
-rw-r--r-- 1 root root 0 9月 22 13:41 /tmp/oldboy_2016-09-22-13-41-11
-rw-r--r-- 1 root root 0 9月 22 13:41 /tmp/oldboy_2016-09-22-13-41-08
-rw-r--r-- 1 root root 0 9月 22 13:41 /tmp/oldboy_2016-09-22-13-41-11
-rw-r--r-- 1 root root 0 9月 22 13:41 /tmp/oldboy_2016-09-22-13-41-14
^C #<==按Ctrl+c键后,发现所有的文件都被清理了,说明已经调用了find清理命令。
[root@oldboy scripts]# ls -l /tmp/
总用量 4
drwx------ 2 oldboy oldboy 4096 9月 22 13:38 ssh-YSpSS25727
范例:开发脚本,练习使用QUIT、TSTP、INT信号。
脚本如下:
[root@oldboy scripts]# cat 17_5.sh
#! /bin/bash
#Author:oldboy training
trap 'echo "you art typing Ctrl-c, sorry, script will not terminate."' INT
#<==捕获Ctrl+c键对应的信号后,执行对应快捷键时就会执行echo命令。
trap 'echo "you art typing Ctrl-\, sorry, script will not terminate."' QUIT
#<==捕获Ctrl+\键对应的信号,执行对应快捷键时就会执行echo命令。
trap 'echo "you art typing Ctrl-z, sorry, script will not terminate."' TSTP
#<==捕获Ctrl+z键对应的信号,执行对应快捷键时就会执行echo命令(实测此处没有执行echo命令)。
while true
do
echo "Now, test signal `date`"
sleep 5
done
测试执行结果如下:
[root@oldboy scripts]# sh 17_5.sh
Now, test signal 2016年 09月 22日 星期四 14:03:09 CST
Now, test signal 2016年 09月 22日 星期四 14:03:14 CST
^Cyou art typing Ctrl-c, sorry, script will not terminate.
#<==按下Ctrl+c键将打印这一行提示。
Now, test signal 2016年 09月 22日 星期四 14:03:15 CST
Now, test signal 2016年 09月 22日 星期四 14:03:20 CST
^\退出
you art typing Ctrl-\, sorry, script will not terminate.
#<==按下Ctrl+\键将打印这一行提示。
Now, test signal 2016年 09月 22日 星期四 14:03:21 CST
Now, test signal 2016年 09月 22日 星期四 14:03:26 CST
^Z^Z #<==按下Ctrl+z键没有打印提示,但是程序停止运行了。
范例:开发企业级Shell跳板机。要求用户登录到跳板机后只能执行管理员给定的选项动作,不允许以任何形式中断脚本而到跳板机服务器上执行任何系统命令。
参考答案1:
-
1)首先做好ssh密钥验证(跳板机地址为192.168.33.128)。
将在所有机器上操作以下命令:[root@oldboy ~]# useradd jump #<==要在所有机器上操作。 [root@oldboy ~]# echo 123456|passwd --stdin jump #<==要在所有机器上操作。 Changing password for user jump. passwd: all authentication tokens updated successfully.仅在跳板机上操作以下命令:
[root@oldboy ~]# su - jump [jump@oldboy ~]$ ssh-keygen -t dsa -P '' -f ~/.ssh/id_dsa >/dev/null 2>&1 #<==生成密钥对。 [jump@oldboy ~]$ ssh-copy-id -i ~/.ssh/id_dsa.pub 192.168.33.130 #<==将公钥分发到其他服务器。 The authenticity of host '192.168.33.130 (192.168.33.130)' can't be established. RSA key fingerprint is fd:2c:0b:81:b0:95:c3:33:c1:45:6a:1c:16:2f:b3:9a. Are you sure you want to continue connecting (yes/no)? yes Warning: Permanently added '192.168.33.130' (RSA) to the list of known hosts. jump@192.168.33.130's password: Now try logging into the machine, with "ssh '192.168.33.130'", and check in: .ssh/authorized_keys to make sure we haven't added extra keys that you weren't expecting. [jump@oldboy ~]$ ssh-copy-id -i ~/.ssh/id_dsa.pub 192.168.33.129 #<==将公钥分发到其他服务器。 The authenticity of host '192.168.33.129 (192.168.33.129)' can't be established. RSA key fingerprint is fd:2c:0b:81:b0:95:c3:33:c1:45:6a:1c:16:2f:b3:9a. Are you sure you want to continue connecting (yes/no)? yes Warning: Permanently added '192.168.33.129' (RSA) to the list of known hosts. jump@192.168.33.129's password: Now try logging into the machine, with "ssh '192.168.33.129'", and check in: .ssh/authorized_keys to make sure we haven't added extra keys that you weren't expecting. -
2)实现传统的远程连接菜单的脚本。
菜单脚本如下:cat <<menu 1)oldboy-192.168.33.129 2)oldgirl-192.168.33.130 3)exit menu -
3)利用Linux信号防止用户中断信号在跳板机上操作。
代码如下:function trapper () { trap ':' INT EXIT TSTP TERM HUP #<==屏蔽这些信号。 } -
4)用户登录跳板机后即调用脚本(不能用命令行管理跳板机),并且只能按管理员的要求选单。
以下为实战内容。将脚本放在跳板机上:
[root@oldboy ~]# echo '[ $UID -ne 0 ] && . /server/scripts/jump.sh' >/etc/ profile.d/jump.sh [root@oldboy ~]# cat /etc/profile.d/jump.sh [ $UID -ne 0 ] && . /server/scripts/jump.sh [root@oldboy scripts]# cat /server/scripts/jump.sh #! /bin/sh #oldboy training trapper() { trap ':' INT EXIT TSTP TERM HUP #<==定义需要屏蔽的信号,冒号表示啥都不做。 } main(){ while : do trapper clear cat <<menu 1)Web01-192.168.33.129 2)Web02-192.168.33.130 menu read -p "Pls input a num.:" num case "$num" in 1) echo 'login in 192.168.33.129.' ssh 192.168.33.129 ;; 2) echo 'login in 192.168.33.130.' ssh 192.168.33.130 ;; 110) read -p "your birthday:" char if [ "$char" = "0926" ]; then exit sleep 3 fi ;; *) echo "select error." esac done } main执行效果如下:
[root@oldboy ~]# su - jump #<==切到普通用户即弹出菜单,工作中直接用jump登录,即弹出菜单。 1)Web01-192.168.33.129 2)Web02-192.168.33.130 Pls input a num.: 1)Web01-192.168.33.129 2)Web02-192.168.33.130 Pls input a num.:1 #<==选1,则进入Web01服务器。 login in 192.168.33.129. Last login: Tue Oct 11 17:23:52 2016 from 192.168.33.128 [jump@littleboy ~]$ #<==按Ctrl+D键退出到跳板机服务器,且再次弹出菜单。 1)Web01-192.168.33.129 2)Web02-192.168.33.130 Pls input a num.:2 #<==选2,则进入Web02服务器。 login in 192.168.33.130. Last login: Wed Oct 12 23:30:14 2016 from 192.168.33.128 [jump@oldgirl ~]$ #<==按Ctrl+D键退出到跳板机服务器,且再次弹出菜单。 1)Web01-192.168.33.129 2)Web02-192.168.33.130 Pls input a num.:110 #<==选110,则进入跳板机命令提示符 your birthday:0926 #<==需要输入特别码才能进入,这里是管理员通道,密码要保密呦。 [root@oldboy scripts]# #<==跳板机管理命令行。

1723

被折叠的 条评论
为什么被折叠?



