前言:
最早需求是因为我的自动化平台远程管理服务器一直是root用户,但经历过运营商的基线扫描后,把root用户限制了,只能用非root用户去管理,jenkins基本就瘫痪了。只能是想其他办法,用非root用户登录服务器,再去切换root身份去构建脚本。不得已,一路踩坑过来。
思路是,原有项目的自动化脚本(B)保持不变,单独新增一个自动切换root用户的脚本(A),然后先运行A,再运行B
命令简单介绍
expect是一个用来实现自动交互功能的软件。
其交互流程是:
spawn启动指定进程 -> expect获取指定关键字 -> send想指定进程发送指定指令 -> 执行完成, 退出。
安装命令:yum install -y expect
适用场景:自动化项目中远程执行命令
expect常用命令总结:
spawn 交互程序开始后面跟命令或者指定程序
expect 获取匹配信息匹配成功则执行expect后面的程序动作
send exp_send 用于发送指定的字符串信息
exp_continue 在expect中多次匹配就需要用到
send_user 用来打印输出 相当于shell中的echo
exit 退出expect脚本
eof expect执行结束 退出
set 定义变量
puts 输出变量
set timeout 设置超时时间
interact 保持用户交互状态
脚本示例
示例1,由非root用户自动切root用户实现
#!/usr/bin/expect
set passwd [lindex $argv 0]
set timeout 30
spawn su root
expect "*:"
send "${passwd}\r"
interact
#########以下为解释说明#####################
1、首行声明此处为非标准shell,调用的expect命令,因此执行该脚本的时候,不能用sh root.sh命令来运行脚本,需要./root.sh
2、set passwd [lindex $argv 0]
此处为向expect脚本传入参数,0代表第一个入参,1代表第二个入参(set abc [lindex $argv 1]),依次类推.
3、set timeout 30
设置超时时间,单位是秒,命令执行的过程,假如是`spawn`后面调用了一个`scp`命令,传输一个很大的文件,有可能文件还没传输完,命令就中断了,此时可以将这个值设置大一点。
4、spawn su root
`spawn`是进入`expect`环境后才可以执行的`expect`内部命令,不是系统`/usr/bin`下面的命令;
`spawn`后面直接加上要执行的命令,此处直接填的切换root用户的命令
5、expect "*:"
`expect`命令的作用就是获取`spawn`命令执行后的信息,看看是否和其事先指定的相匹配。一旦匹配上指定的内容就执行expect后面的动作
6、send "${passwd}\r"
在expect命令匹配指定的字符串后,`send`命令发送指定的字符串给系统,这些命令可以支持一些特殊转义符号,例如:\r表示回车、\n表示换行、\t表示制表符
7、interact 执行完成后保持交互状态,把控制权交给控制台
总结:用这个脚本,是实现了非root切换到root用户
但是放到jenkins下又不行了,具体什么原因不清楚了。
示例2,调整命令结构,shell的写法
#!/usr/bin/sh
#部署机器信息
remote_ip="$1"
#root密码
remote_pwd="$2"
#调用脚本B的构建命令
runim="$3"
echo -e "执行远程机器上的部署脚本...\n"
expect <<EOF >&1
set timeout 300
spawn ssh -p 6007 root@${remote_ip}
expect {
timeout {puts "Unable to access the host"; exit -1}
"*yes/no" { send "yes\n";exp_continue}
"*assword:" { send "${remote_pwd}\n" }
}
expect "]#" { send "${runim}\n" }
expect "]#" { send "exit\n" }
expect eof
EOF
然后就可以了。当然这个脚本B的构建命令的特殊字符也是折腾半天。