我们经常需要进行一些自动化,定时运行的脚本时。
经常会需要我们手动输入的情况。为了绕过这些交互式的验证。我选择使用 sshpass
和 expect
来解决。
sshpass
sshpass
是一个简单、轻量级的命令行工具,通过它我们能够向命令提示符本身提供密码(非交互式密码验证)。
安装:
yum install sshpass -y
使用:
sshpass -p <password> ssh -o StrictHostKeyChecking=no <username>@<ip> "command"
示例:
# 远程执行命令
sshpass -p <password> ssh -o StrictHostKeyChecking=no <root>@<ip> "ls -al"
# 远程连接
sshpass -p <password> ssh -o StrictHostKeyChecking=no <root>@<ip>
expect
expect
是基于 TCL
的相对简单的一个免费脚本编程工具语言,用来实现自动和交互式任务进行通信,无需人的手工干预。
安装:
yum install -y expect
常用用法:
-
send
: 用于向进程发送字符串 -
expect
: 从进程接收字符串 -
spawn
: 启动新的进程 -
interact
: 允许用户交互,把控制权交给控制台,这个时候就可以手工操作了 -
expect eof
: 这个与spawn
对应表示捕获终端输出信息终止,类似于if….endif
特别说明下:
-
send
命令接收一个字符串参数,并将该参数发送到进程中去,一般用来发送到spawn
命令启动的进程中去。 -
expect
命令和send
命令正好相反,expect
命令通常是用来等待一个进程的反馈。 -
expect
命令可以接收一个字符串参数,也可以接收正则表达式参数。一般用来等待spawn
命令启动的进程的反馈。
示例:
使用 expect
来远程登陆 ssh
#!/usr/bin/expect
# 告诉系统使用那个shell来执行文件
set timeout 30
# 设置超时时间的秒数, timeout -1 为永不超时
set HOST [lindex $argv 0]
# 将第一个参数赋值给HOST变量
set PASSWORD [lindex $argv 1]
# 将第二个参数赋值给PASSWORD变量
spawn ssh root@$HOST
# 启动新的进程,该进程使用 root 账号 ssh 远程登陆 $HOST 地址
expect {
"yes/no" {
send "yes\r";
exp_continue
}
"password:" {
send "$PASSWORD\r"
}
}
# 多分支等待ssh进程的反馈
# 如果字符串中包含 yes/no 时,执行分支一
# 如果字符串中包含 password: 时,执行分支二
# 其中 exp_continue 附加于某个 expect 判断项之后,可以使该项被匹配后,还能继续匹配该 expect 判断语句
# 关于 \r 是因为 expect的字符处理是没有换行符之类的,所以需要额外加上
expect "*#"
send "ll -a\r"
# 以上两句是单分支匹配到 # 时执行 ll -a
expect eof
exit
# expect eof和exit是指监测到eof就会执行exit,退出程序。
在 bash 中嵌套使用 expect ,示例中进行 maven 自动打包
#!/usr/bin/env bash
DIR_LIST=("module1" "module2" "module3" "module_build" "module4" "module5")
PASSWORD="password\r"
for dir in ${DIR_LIST[@]}
do
# echo $dir
if [ -d "$dir" ]; then
rm -rf "$dir"
fi
GIT_URL="git clone -b dev xxx@xx.xx.xx.xx:/gitrepo/xxx/$dir"
# echo $GIT_URL
/usr/bin/expect <<-EOF
set timeout -1
spawn $GIT_URL
expect "*password:"
send $PASSWORD
expect eof
EOF
echo -e "\n"
done
sleep 1
mvn clean install -f module_build/ -Dmaven.test.skip=true