目录
一 信号处理
# 1 什么是信号
由键盘组合键或者kill命令发出操作称之为信号
信号是发送给进程的,进程在收到信号后会作出默认的响应
# 2 为何要在进程内处理信号
进程在收到信号后会有默认的响应,
如果我们想改变进程在接收到信号后的反应,那么需要在进程内捕捉信号执行我们自定义的操作
# 3 主要的应用场景:
在进程内捕捉终止信号,然后忽略掉,从而达到让进程不受外界干扰正常运行完毕的效果
ps:不是所有的信号都可以被捕捉,比如-9
3、如何处理信号
trap "捕捉到信号之后要执行的命令" 信号
trap "" 信号 # 如不指定执行信息则当做不做处理
trap "" 信号1 信号2 信号3 # 多个信号都不做处理
trap信号列表
信号 | 说明 |
---|---|
HUP | 挂起,通常因终端掉线或用户退出而引发 |
INT | 中断,通常因按下Crtl+C组合健而引发 |
QUIT | 退出,通常因某些严重的执行错误而引发 |
TERM | 终止,通常在系统关机时发送 |
TSTP | 停止进程的运行,但该信号可以被处理和忽略,用户健入SUSP字符时(通常是Ctrl-Z)发出这个信号 |
ABRT | 中止,通常因某些严重的执行错误而引发 |
- 示例如
# 使用此方式执行脚本,对键盘执行的ctrl+c ctrl+z等其他操作都不会进行操作,以往执行ctrl+c都是停止。
· 这里主要实现对脚本循环执行红绿灯,并且此脚本执行过程中不受下方信号影响。
[root@tcy day07]# cat 3.sh
#!/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
HUP信号的处理:让一个进程脱离当前会话窗口运行
nohup脱离父进程
-
(需将其终端关闭,才能将父进程改变为系统进程,否则为终端进程)
# 在终端2内 [root@tcy ~]# echo $$ 12479 [root@tcy ~]# nohup ping www.baidu.com & # 关闭终端2 # 在终端1内仍然可以看到进程(但其父进程为系统进程) [root@tcy ~]# ps -ef |grep [p]ing root 13169 1 0 18:58 ? 00:00:00 ping www.baidu.com
-
setsid(直接让父进程为系统进程)
setsid ping www.baidu.com &
-
(进程 &) 直接让父进程为系统进程
(ping www.tcy.com &) [root@db01 ~]# ps -ef|grep tcy root 8333 1 0 22:46 pts/1 00:00:00 ping www.tcy.com root 8360 8336 0 22:46 pts/2 00:00:00 grep --color=auto tcy
二 expect
expect介绍
在使用expect
时,基本上都是和以下四个命令打交道:
命令 | 作用 |
---|---|
spawn | 启动新的进程 |
expect | 从进程接收字符串 |
send | 用于向进程发送字符串 |
interact | 允许用户交互 |
spawn
命令用来启动新的进程,spawn
后的expect
和send
命令都是和使用spawn
启动的新进程进行交互。expect
通常用来等待一个进程的反馈,我们根据进程的反馈,再使用send
命令发送对应的交互命令。send
命令接收一个字符串参数,并将该参数发送到进程。interact
命令用的其实不是很多,一般情况下使用spawn
、expect
和send
和命令就可以很好的完成我们的任务;但在一些特殊场合下还是需要使用interact
命令的,interact
命令主要用于退出自动化,进入人工交互。比如我们使用spawn
、send
和expect
命令完成了ftp登陆主机,执行下载文件任务,但是我们希望在文件下载结束以后,仍然可以停留在ftp命令行状态,以便手动的执行后续命令,此时使用interact
命令就可以很好的完成这个任务。
expect基本使用
# 前期需要安装expect安装包
[root@db01 day08]# yum install -y expect
# send指令提交方式(两者都可对指令进行提交)
[root@tcy day07]# cat 4.sh
#!/usr/bin/expect # 这里虽然是脚本,但是需要指定解释器为expect
spawn ssh root@127.0.0.1 hostname # 执行进程操作指令
expect "yes/no" # 等待进程反馈,匹配yes/no的指令
send "yes
" # 根据expect匹配的指令进行操作,也就是直接帮助yes提交
expect "assword" # 继续等待进程反馈,屁屁额assword指令
send "1
" # 根据匹配的指令进行1操作,这里也就是我的密码
expect eof # 结束交互指令
# 总结:
这种操作存在弊端,只适用于第一次连接,如第二次进行ssh连接,可忽略yes步骤,直接输入密码即可,expect比较愚蠢,
不会只能匹配,而是在第二次连接时当需要输入密码,直接也将第一次匹配的yes直接发送,也就导致了后续的报错。
所以这里为了解决此问题,可参考expect一问一答中的案例操作。
强调:我们此时编写的是expect脚本,不要用sh 4.sh执行,可以./4.sh运行,也可以expect 4.sh运行
expect 一问一答(推荐使用)
# 这里会根据进程指令自动匹配,所以需要将操作匹配指令写入同一个expect中进行处理。
#!/usr/bin/expect
spawn ssh root@127.0.0.1 hostname
expect {
"yes/no" {send "yes
";exp_continue}
"*assword" {send "1
";}
}
expect eof
远程登录主机执行多条命令
# 可免交互式登录主机执行多条语句,注意,这里都是expect语句,不能按照shell语句方式执行
[root@tcy day07]# cat 6.sh
#!/usr/bin/expect
spawn ssh root@127.0.0.1
expect {
"yes/no" {send "yes
";exp_continue}
"*assword" {send "1
";}
}
expect {
"#" {send "ls
"} # 这里为匹配#交互式指令,到匹配到就执行ls命令
}
expect {
"*root*" {send "pwd
"} # 这里为匹配root交互式指令,匹配到就执行pwd指令
}
expect {
"#" {send "exit
"} # 这里为匹配# 指令,匹配到就执行exit指令,相当于回到自己的终端
}
expect eof # 结束交互式操作,但还在远程的终端中,超时才会自动退出
interact(了解)
[root@tcy day07]# cat 7.sh
#!/usr/bin/expect
spawn ssh tcy@127.0.0.1
expect {
"yes/no" {send "yes
";exp_continue}
"*assword" {send "1
";}
}
expect {
"*tcy*" {send "ls
"}
}
expect {
"*tcy*" {send "pwd
"}
}
interact # 运行完以上指令,不进行超时退出,任然停留在远程终端中
expect eof
在expect脚本中定义变量
# 使用的并不是bash解释器,所以需要expect自身语法。
#!/usr/bin/expect
set user "root" # 类似于bash的定义变量user=root
set pass "1"
set ip "127.0.0.1"
set cmd "hostname"
spawn ssh $user@$ip $cmd # 调用上方定义变量开启进程
expect {
"yes/no" {send "yes
";exp_continue}
"*assword" {send "$pass
";}
}
expect eof
把expect引入shell脚本(推荐使用)
# 单学expect较为复杂,可将expect引入bash中。
#!/bin/bash # 使用bash解释器
user="root" # 使用bash的方式定义变量
pass="1"
ip="127.0.0.1"
cmd="hostname"
expect << EOF # 引expect在bash中也是一个命令,所以将其
spawn ssh $user@$ip $cmd # 内容放入一个内容体当中
expect {
"yes/no" {send "yes
";exp_continue}
"*assword" {send "$pass
";}
}
expect eof
EOF
echo "success!!!"