expect可以让我们实现自动登录远程机器,并且可以实现自动远程执行命令。当然若是使用不带密码的密钥验证同样可以实现自动登录和自动远程执行命令。但当不能使用密钥验证的时候,我们就没有办法了。所以,这时候只要知道对方机器的账号和密码就可以通过expect脚本实现登录和远程命令。
分发准备:模板脚本、服务器ip、用户名、密码、expect脚本
yum install -y expect
expect脚本登录机器:
vim 1.expect #!/usr/bin/expect set host "192.168.133.132" #连接到主机 set passwd "123456" #密码 spawn ssh root@$host #spawn调用shell命令ssh(登录),“set host”和“set passwd”为expect定义的两个变量 expect { "yes/no" { send "yes\r"; exp_continue} #ssh首次远程登录一台主机是会提示yes/no,吧yes发送过去;"\r“表示回车 "password:" { send "$passwd\r" } #如果提示passwd需要把密码发送过去,用户交互,"\r“表示回车 } interact #interact的作用是停留在远程机器上,不退出 #脚本结束符号:expect eof——执行结束后暂停几秒钟后退出 #如果不加任何结束符号,命令执行完后马上退出
注意的是需要755权限,即chmod a+x 1.expect
执行该脚本使用:./1.expect
expect脚本远程执行命令:
vim 2.expect #!/usr/bin/expect set user "root" set passwd "123456" spawn ssh $user@192.168.133.132 expect { "yes/no" { send "yes\r"; exp_continue} "password:" { send "$passwd\r" } } expect "]*" #匹配到“]”指的是登录成功后左边的用户信息的右括号,意思是登录成功后执行下面的命令 send "touch /tmp/12.txt\r" "\r“表示回车,然后又匹配到左边的的用户信息括号 expect "]*" send "echo 1212 > /tmp/12.txt\r" "\r“表示回车,然后又匹配到左边的的用户信息括号 expect "]*" send "exit\r"
expect脚本传递参数:
vim 3.expect #!/usr/bin/expect #调用内部参数,用户名ip密码,在执行的时候直接调用 set user [lindex $argv 0] set host [lindex $argv 1] set passwd "123456" set cm [lindex $argv 2] #这个是第三个参数,就是要执行的命令,比如ls spawn ssh $user@$host expect { "yes/no" { send "yes\r"} "password:" { send "$passwd\r" } } expect "]*" send "$cm\r" expect "]*" send "exit\r" #如果需要执行多条命令使用;分隔和双引号,比如“ls;w;cat 1.txt” #expect存在超时时间,不适合运行vmstart这种命令 #如果想要修改超时时间,在send "$cm\r"下一行加上 set timeout -1 永久不超时 set timeout 5 五秒时间推出
expect脚本同步文件:
vim 4.expect #!/usr/bin/expect set passwd "123456" spawn rsync -av root@192.168.204.137:/tmp/12.txt /tmp/ #把远程机器上的12.txt同步到本机 expect { "yes/no" { send "yes\r"} "password:" { send "$passwd\r" } } expect eof #脚本结束符号:expect eof——执行结束后暂停几秒钟后退出
expect脚本指定host和要同步的文件:
vim 5.expect #!/usr/bin/expect set passwd "123456" set host [lindex $argv 0] set file [lindex $argv 1] spawn rsync -av $file root@$host:$file #file写绝对路径 expect { "yes/no" { send "yes\r"} "password:" { send "$passwd\r" } } expect eof chmod a+x 5.expect touch 1.txt ./5.expect 192.168.133.132 "/tmp/1.txt"
构建文件分发系统
这里思路为首先写expect脚本,然后提供参数,最后使用shell脚本实现分发功能
#第一步写expect脚本,最后shell也是调用到了这里来实现功能 vim rsync.expect #!/usr/bin/expect set passwd "123456" set host [lindex $argv 0] set file [lindex $argv 1] #这里指的对应IP和文件列表,在最后的shell脚本中来实现 spawn rsync -av --files-from=$file / root@$host:/ #如果不能保证对方机器有相同路径加上-avR expect { "yes/no" { send "yes\r"} "password:" { send "$passwd\r" } } expect eof
#第二步提供要被传送的文件的集合,也就是exoect脚本的第二个参数file vim list.txt /root/shell/1.sh ... ... #该文件下可添加多个文件,这个就是要传送的文件了
#第三步定义对应ip的内容,也就是expect的host参数 vim iplist.txt 192.168.133.132 192.168.133.133 ...... #此处IP(主机)密码要和rsync.expect脚本中一致。为了避免密码泄露的风险,可以使用密钥认证的方法
#最后shell脚本实现功能 vim rsync.sh #!/bin/bash for ip in `cat iplist.txt` do echo $ip ./rsync.expect $ip list.txt done #该脚本作用是遍历文件和ip列表
批量远程执行命令
#第一步expect脚本调用host和具体的命令$cm vim exe.expect #!/usr/bin/expect set host [lindex $argv 0] #第一个变量 set passwd "123456" set cm [lindex $argv 1] #第二个变量 spawn ssh root@$host expect { "yes/no" { send "yes\r"} "password:" { send "$passwd\r" } } expect "]*" send "$cm\r" expect "]*" send "exit\r" #该脚本作用是远程执行命令 chmod a+x exe.expect
#然后定义shell脚本,指定ip和使用的命令 #执行此脚本的目的是一次性多台机器执行相同命令,所有shell中定义需执行的命令 vim exe.sh #!/bin/bash for ip in `cat iplist.txt` do echo $ip ./exe.expect $ip "w;free -m;ls /tmp" done #该脚本的作用是调用iplist.txt文件中的IP和exe.expect脚本