今天第一次在shell脚本中接触到expect工具,开启了脚本交互式的编程。在以前的脚本中,关于怎么远程执行指令的问题有一篇文章-“Linux怎么远程执行指令呢-SSH秘钥”,即通过密钥对部署,在远程时免去输入密码,最后可以通过ssh 192.168.31.82 "ls" 来远程执行“ls”指令。但是,如果系统中有很多台Linux服务器呢,两两间配置密钥就太麻烦。今天偶遇expect工具,可以完成交互通信。
expect是一个自动化交互套件,主要应用于执行命令和程序时,系统以交互形式要求输入指定字符串,实现交互通信。
expect自动交互流程:spawn启动指定进程---expect获取指定关键字---send向指定程序发送指定字符---执行完成退出。
1、安装expect工具
sudo apt install expect
查看expect在哪个目录,便于后续在脚本中使用,运行命令which expect,显示在/usr/bin/expect。
2、expect常用命令
spawn :交互程序开始后面跟命令或者指定程序
expect :获取匹配信息匹配成功则执行expect后面的程序动作
send exp_send: 用于发送指定的字符串信息
exp_continue : 在expect中多次匹配就需要用到
send_user : 用来打印输出 相当于shell中的echo
exit : 退出expect脚本
eof : expect执行结束 退出
set : 定义变量
puts : 输出变量
set timeout : 设置超时时间
3、远程查看mysql进程是否正常
运行下面的脚本,用用户户名pi和密码password远程到192.168.31.103并执行查看mysql进程的命令,如果进程存在则后返回1 ,进程不存在则返回0。wc -l是计算行数。
#!/bin/bash
passwd='password'
/usr/bin/expect <<-EOF
set time 30
spawn ssh pi@192.168.31.103 ps -ef |grep mysql | grep -v grep | wc -l
expect {
"*yes/no" { send "yes\r"; exp_continue }
"*password:" { send "$passwd\r" }
}
expect eof
EOF
如果把命令ps -ef |grep mysql | grep -v grep | wc -l 替换成sudo pkill mysqld,即杀掉mysql进程,那么使用下面的命令,不挂起不输出的执行杀进程的脚本。
nohup ./expect.sh >/dev/null 2>&1
4、打包成脚本zlssh
#!/usr/bin/expect
set timeout 10
if { $argc<3 } {
puts "Usage:"
puts "$argv0 remote_host command"
exit 1
}
set remote_host [lindex $argv 0]
set passwd [lindex $argv 1]
set command [lindex $argv 2]
spawn ssh $remote_host $command
expect {
"password:" {
send "$passwd\r"
exp_continue
}
"(yes/no)?" {
send "yes\r"
exp_continue
}
timeout {
puts "connect is timeout"
exit 3
}
}
$argc代表参数个数,参数值存放在$argv中。运行./zlssh 192.168.31.103 password "ps -ef |grep mysql | grep -v grep | wc -l"可以得到相同的结果,./zlssh 写成绝对路径会更加好。在其他脚本中就可以直接使用这个命令来完成不同的linux,不同的命令执行,提高工作效率。
最后可以在脚本里面读取hosts里面的ip列表,然后使用打包好的zlssh 命令来循环执行指令,就可以完成局域网中多台linux系统的运维工作。
网友评论