Shell 中的信号处理与expect自动交互
本篇内容:
1、信号处理
2、expect
信号处理
1 什么是信号
由键盘组合键或者kill命令发出操作称之为信号
信号是发送给进程的,进程在收到信号后会作出默认的响应
2 为何要在进程内处理信号
进程在收到信号后会有默认的响应,
如果我们想改变进程在接收到信号后的反应,那么需要在进程内捕捉信号执行我们自定义的操作
主要的应用场景:
在进程内捕捉终止信号,然后忽略掉,从而达到让进程不受外界干扰正常运行完毕的效果
ps:不是所有的信号都可以被捕捉,比如-9
3、如何处理信号
trap "捕捉到信号之后要执行的命令" 信号
trap "" 信号
trap "" 信号1 信号2 信号3
示例如
[root@egon 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 "\033[31m 红灯亮 \033[0m"
else
echo -e "\033[32m 绿灯亮 \033[0m"
fi
sleep 0.5
clear
done
[root@egon day07]#
HUP信号的处理:让一个进程脱离当前会话窗口运行
nohup
setsid
setsid
重新创建一个session,子进程从父进程继承了SessionID、进程组ID和打开的终端,子进程如果要脱离父进程,不受父进程控制,我们可以用这个setsid命令
setsid ping www.baidu.com &
进程 &
作用同上
(ping www.baidu.com &)
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解释器
yum install -y expect
# 这是expect脚本,需要用#!/usr/bin/expect来解释,不能用sh执行,可以用./或expect来执行.
其中\n和\r都表示回车,都可以使用.
问题: 如果已经执行过连接,下次连接就不会再要求输入yes/no了,会导致错误.
[root@zabbix ~]# vim 4.sh
=======================
#!/usr/bin/expect
spawn ssh root@127.0.0.1 hostname
set timeout -1 #设置没有超时时间
set timeout 2 #设置超时时间为2秒
spawn ssh root@127.0.0.1 hostname
expect "yes/no"
send "yes\r"
expect "assword"
send "1\n"
expect eof
[root@egon day07]#
强调:我们此时编写的是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\n";exp_continue}
"*assword" {send "1\n";}
}
expect eof
远程登录主机执行多条命令
[root@egon day07]# cat 6.sh
#!/usr/bin/expect
spawn ssh root@127.0.0.1
expect {
"yes/no" {send "yes\n";exp_continue}
"*assword" {send "1\n";}
}
expect {
"#" {send "ls\n"}
}
expect {
"*root*" {send "pwd\n"}
}
expect {
"#" {send "exit\n"}
}
expect eof
[root@egon day07]#
interact(了解)
# 让自动执行的脚本返回到交互式状态interact
[root@egon day07]# cat 7.sh
#!/usr/bin/expect
spawn ssh egon@127.0.0.1
expect {
"yes/no" {send "yes\n";exp_continue}
"*assword" {send "1\n";}
}
expect {
"*egon*" {send "ls\n"}
}
expect {
"*egon*" {send "pwd\n"}
}
interact
[root@egon day07]#
在expect脚本中定义变量
#!/usr/bin/expect
set user "root"
set pass "1"
set ip "127.0.0.1"
set cmd "hostname"
spawn ssh user@ip cmd
expect {
"yes/no" {send "yes\n";exp_continue} "*assword" {send "pass\n";}
}
expect eof
----------------------------
if {$argc !=4} # expect中用于取变量的个数
puts # expect中相当于echo
把expect引入shell脚本
#!/bin/bash
user="root"
pass="1"
ip="127.0.0.1"
cmd="hostname"
expect << EOF
spawn ssh user@ip cmd
expect {
"yes/no" {send "yes\n";exp_continue} "*assword" {send "pass\n";}
}
expect eof
EOF
echo "success!!!"