06 信号处理和expect

信号说明

在执行脚本的过程中,可能会被一些键盘操作的快捷方式所打断,影响脚本的运行

常用信号

# HUP(1):  1、挂起信号 2、往往可以让进程重新加载配置
本信号在用户终端连接(正常或非正常)结束时发出, 通常是在终端的控制进程结束时, 通知同一session内的各个作业, 这时它们与控制终端不再关联。

登录Linux时,系统会分配给登录用户一个终端(Session)。在这个终端运行的所有程序,包括前台进程组和后台进程组,一般都 属于这个 Session。当用户退出Linux登录时,
前台进程组和后台有对终端输出的进程将会收到SIGHUP信号。这个信号的默认操作为终止进程,因此前台进 程组和后台有终端输出的进程就会中止。不过,可以捕获这个信号,
比如wget能捕获SIGHUP信号,并忽略它,这样就算退出了Linux登录,wget也 能继续下载。

此外,对于与终端脱离关系的守护进程,这个信号用于通知它重新读取配置文件。

# INT(2):  中断, 通常因为按下ctrl+c而产生的信号,用于通知前台进程组终止进程。
# QUIT(3): 退出,和SIGINT类似, 但由QUIT字符(通常是Ctrl-\)来控制. 进程在因收到SIGQUIT退出时会产生core文件, 在这个意义上类似于一个程序错误信号。

# TSTP(20): 停止进行运行,通常因为按下ctrl+z而产生的信号

# KILL (9)
用来立即结束程序的运行. 本信号不能被阻塞、处理和忽略。如果管理员发现某个进程终止不了,可尝试发送这个信号。
# TERM(15): 
终止,是不带参数时kill默认发送的信号,默认是杀死进程,与SIGKILL不同的是该信号可以被阻塞和处理。通常用TERM信号来要求程序自己正常退出,如果进程终止不了,我们才会尝试SIGKILL。
  
# ===============了解===============
# ABRT(6): 中止, 通常因某些严重错误产生的引号   

# SIGCHLD 
子进程结束时, 父进程会收到这个信号。

如果父进程没有处理这个信号,也没有等待(wait)子进程,子进程虽然终止,但是还会在内核进程表中占有表项,
这时的子进程称为僵尸 进程。这种情 况我们应该避免(父进程或者忽略SIGCHILD信号,或者捕捉它,或者wait它派生的子进程,或者父进程先终止,
这时子进程的终止自动由init进程 来接管)。

# 更多详见:man 7 signal

捕捉

# 操作1:捕捉信号、执行引号内的操作
trap "echo 已经识别中断信号:ctrl+c" INT

# 示例2:捕捉信号、不执行任何操作
trap "" INT  

# 示例3:也可以同时捕获多个信号
trap "" HUP INT QUIT TSTP

expect

expect是一个免费的编程工具,用来实现自动的交互式任务,而无需人为干预。说白了,expect就是一套用来实现自动交互功能的软件。

基础介绍

yum install -y expect
spawn命令用来启动新的进程,spawn后的expect和send命令都是和使用spawn启动的新进程进行交互。

expect通常用来等待一个进程的反馈,我们根据进程的反馈,再使用send命令发送对应的交互命令。

send命令接收一个字符串参数,并将该参数发送到进程。

interact命令用的其实不是很多,一般情况下使用spawn、expect和send和命令就可以很好的完成我们的任务;但在一些特殊场合下还是需要使用interact命令的,interact命令主要用于退出自动化,进入人工交互。比如我们使用spawn、send和expect命令完成了ftp登陆主机,执行下载文件任务,但是我们希望在文件下载结束以后,仍然可以停留在ftp命令行状态,以便手动的执行后续命令,此时使用interact命令就可以很好的完成这个任务。

基本步骤

第一步: 运行一个程序或命令=>  spawn 命令信息
第二步: 识别产生信息关键字=>  expect 捕获关键字   {send  应答信息}
第三步: 根据识别关键做处理=>  send  应答信息

基本语法

expect << EOF
	需要交互的代码块
	expect{
	"询问1"{send "操作\r(确认)";exp_continue}
	"询问2"{send "操作\n(确认)";exp_continue}
	"询问3"{send "操作\n"}
	}
	expect eof

EOF

案例

#!/bin/bash/expect

while read line
do
user=`echo $line | awk -F: '{print $1}'` #user
old_pwd=`echo $line | awk -F: '{print $2}'` #old password
new_pwd=`echo $line | awk -F: '{print $3}'` #new password
ip=`echo $line | awk -F: '{print $4}'` #ip

expect << EOF
    spawn ssh $user@$ip passwd

    expect {
            "yes/no" {send "yes\r";exp_continue}
            "*assword" {send "$old_pwd\n"}
    }
    expect {
            "*assword" {send "$new_pwd\n";exp_continue}
            "*assword" {send "$new_pwd\n"}

    }
    expect eof

EOF
done</tmp/passwd.txt
posted @ 2021-06-17 15:29  BaiM0  阅读(84)  评论(0编辑  收藏  举报