使用expect之前需要先安装
yum –y intall expect
send:向进程发送字符串,用于模拟用户的输入
该命令不能自动回车换行,一般要加 \r(回车)
expect:expect的一个内部命令,判断上次输出结果里是否包含指定的字符串,如果有则立即返回,否则就等待超时时间后返回。只能捕捉由spawn启动的进程的输出
spawn:启动进程,并跟踪后续交互信息
interact:执行完成后保持交互状态,把控制权交给控制台
Timeout:指定超时时间,过期则继续执行后续指令
exp_continue:允许expect继续向下执行指令
send_user:回显命令,相当于echo
$argv 参数数组:Expect脚本可以接受从bash传递的参数.可以使用[lindex $argv n]获得,n从0开始,分别表示第一个,第二个,第三个…参数
Expect脚本必须以interact或expect eof结束,执行自动化任务通常expect eof就够了
#!/bin/bash
#安装expect
rpm -q expect &>/dev/null
if [ $? -ne 0 ];then
yum install -y expect >/dev/null
echo "expect安装成功"
fi
#设置挂载硬盘的参数
fdisk -l |egrep '^Disk /dev/sd.*'
read -p "请输入需要挂载得硬盘路径: " disk_new
partitions="${disk_new}1"
#expect交互脚本
/usr/bin/expect << EOF
set timeout 30
spawn bash -c "fdisk $disk_new"
expect "Command*" {send "n\r"}
expect "*p*" {send "p\r"}
expect "*1*" {send "\r"}
expect "First*" {send "\r"}
expect "Last*" {send "\r"}
expect "*help*" {send "wq\r"}
expect eof
interact
EOF
#格式化磁盘
mkfs -t xfs $partitions
#挂载
read -p "输入需要挂载得路径:" target_dir
if [ ! -d $target_dir ]
then
mkdir -p $target_dir
fi
echo "$partitions $target_dir xfs defaults 0 0" >> /etc/fstab
#重载fstab配置
mount -a
df -Th
需求1:A远程登录到server上什么都不做
#!/usr/bin/expect
# 开启一个程序
spawn ssh root@10.1.1.1
# 捕获相关内容
expect {
"(yes/no)?" { send "yes\r";exp_continue }
"password:" { send "123456\r" }
}
interact # interact 这个写在最后代表交互,如果不写执行完动作就会退出
脚本执行方式:
# ./expect.sh
# /shell/expect.sh
# expect -f expect.sh
1)定义变量
#!/usr/bin/expect
set ip 192.168.188.188
set pass 123
set timeout 5
spawn ssh root@$ip
expect {
"yes/no" { send "yes\r";exp_continue }
"password:" { send "$pass\r" }
}
interact
2)使用位置参数
#!/usr/bin/expect
set ip [ lindex $argv 0 ]
set pass [ lindex $argv 1 ]
set timeout 5
spawn ssh root@$ip
expect {
"yes/no" { send "yes\r";exp_continue }
"password:" { send "$pass\r" }
}
interact
需求2:A远程登录到server上操作
#!/usr/bin/expect
set ip 192.168.188.188
set pass 123
set timeout 5
spawn ssh root@$ip
expect {
"yes/no" { send "yes\r";exp_continue }
"password:" { send "$pass\r" }
}
expect "#"
send "rm -rf /tmp/*\r" # 删除临时文件
send "touch /tmp/file{1..3}\r" # 创建临时文件
send "date\r"
send "exit\r"
expect eof
需求3:shell脚本和expect结合使用,在多台服务器上创建1个用户
[root@server shell04]# cat ip.txt
192.168.188.188 123
192.168.188.186 123
1. 循环 useradd username
2. 登录远程主机——>ssh——>从ip.txt文件里获取IP和密码分别赋值给两个变量
3. 使用expect程序来解决交互问题
#!/bin/bash
# 循环在指定的服务器上创建用户和文件
while read ip pass
do
/usr/bin/expect <<-EOF &>/dev/null
spawn ssh root@$ip
expect {
"yes/no" { send "yes\r";exp_continue }
"password:" { send "$pass\r" }
}
expect "#" { send "useradd maomao;rm -rf /tmp/*;exit\r" }
expect eof
EOF
echo "$ip服务器用户创建完毕"
done < ip.txt
#!/bin/bash
#自动连接ftp服务器然后下载pub下面的test.txt
#by stanZ 2021-1-27
if [ $# -eq 0 ];then
echo "用法:`basename $0` ftp服务器ip地址"
exit 1
fi
pgrep firewalld &>/dev/null
if [ $? -eq 0 ];then
systemctl stop firewalld &>/dev/null
fi
if [[ $(getenforce) == Enforcing ]];then
setenforce 0
sed -ri '/^SELINUX=/cSELINUX=disabled' /etc/selinux/config &>/dev/null
fi
rpm -q expect &>/dev/null
if [ $? -ne 0 ];then
[ $UID -eq 0 ] && yum install -y expect &>/dev/null || echo "你没有权限安装expect"
fi
{
/usr/bin/expect <<-EOF
set timeout 5
spawn ftp $1
expect {
"):" { send "ftp\r";exp_continue }
"Password:" { send "\r" }
}
expect "ftp>"
send "cd pub\r"
send "get test.txt\r"
send "bye\r"
expect eof
EOF
}&>/dev/null
wait
echo "test.txt文件下载完毕"
写一个脚本,将跳板机上yunwei用户的公钥推送到局域网内可以ping通的所有机器上
说明:主机和密码文件已经提供
192.168.188.188:123
192.168.188.186:123
步骤分析
这里要实现功能 要切换成yunwei账户 必须写两个脚本文件
第一个脚本由root执行
第二个脚本由运维执行
#!/bin/bash
#ssh自动上传公钥,并且能远程控制
#by stanZ 2021-1-11
# 判断防火墙是否关闭
pgrep firewalld &>/dev/null
if [ $? -eq 0 ];then
systemctl stop firewalld &>/dev/null # 关闭防火墙
fi
# 关闭selinux安全中心
if [[ $(getenforce) = Enforcing ]];then
setenforce 0
sed -ri '/^SELINUX=/cSELINUX=disabled' /etc/selinux/config &>/dev/null
fi
{
id yunwei &>/dev/null # 判断yunwei账户是否存在 不存在则创建
[ $? -ne 0 ] && useradd yunwei && echo 123|passwd --stdin yunwei
# 给yunwei账户sudo授权 取消注释
sed -ri 's/^#(.*required.*)/\1/' /etc/pam.d/su
sed -ri 's/^#(.*NOPASSWD)/\1/' /etc/sudoers
# 加入wheel组拥有权限
gpasswd -a yunwei wheel
} >/dev/null
# 判断expect是否安装
rpm -q expect &>/dev/null
if [ $? -ne 0 ];then
yum install -y expect >/dev/null
echo "expect安装成功"
fi
su - yunwei
补充:
[ ! -f /root/.ssh/id_rsa.pub ] && ssh-keygen -P '' -f /root/.ssh/id_rsa
ssh-keygen -P'' 设定密码为空
-f /root/.ssh/id_rsa 指定密钥位置
这样就不需要交互操作
#!/bin/bash
#ssh自动上传公钥,并且能远程控制
#by stanZ 2021-1-11
# 判断私钥是否创建 如果没创建则使用免交互的命令
if [ ! -f /home/yunwei/.ssh/id_rsa ];then
ssh-keygen -P '' -f ~/.ssh/id_rsa &>/dev/null
fi
while read ip pass
do
{
ping -c1 $ip
if [ $? -eq 0 ];then
echo $ip >> /home/yunwei/ip_up.txt
/usr/bin/expect <<-EOF
set timeout 10
spawn ssh-copy-id root@$ip
expect "(yes/no)" { send "yes\r";exp_continue }
expect "password:" { send "$pass\r" }
expect eof
EOF
else
echo $ip >> /home/yunwei/ip_down.txt
fi
}&>/dev/null
done < /home/ip.txt
wait
echo "公钥推送完毕,准备测试"
remote_ip=`head -1 /home/yunwei/ip_up.txt`
ssh root@$remote_ip hostname &>/dev/null
test $? -eq 0 && echo "公钥成功推送,并且能远程连接"