【Linux Shell脚本编程】expect解决脚本交互 + Shell的多进程处理
如果在没有使用密钥认证的情况下,想通过SSH来传输文件给多个主机会面临交互的问题,这在脚本中是非常不友好的。要解决这个问题的话可以使用expect这个工具,它的功能就是提前把交互中需要的内容先写好,然后在脚本执行的时候自动输入。通常用这个工具解决秘钥分发的问题,之后有了秘钥就不需要再使用它了。
1、使用yum安装expect
yum -y expect
2、编写一个使用expect解决ssh交互问题的案例
vi expect.sh #!/bin/expect spawn ssh root@192.168.1.100 #让expect处理该会话,也就是说执行该命令后遇到的交互内容将由expect继续 #下面是提前输入了可能会遇到的交互的内容以及应答方式 expect { "yes/no" { send "yes\r"; exp_continue } #遇到引号内的关键词就发送yes指令, 代表回车,后面的exp_continue表示没有遇到的话继续往下执行 "password" { send "centos\r" }; } interact #让会话保留在对方那边。因为是ssh连接,所以要保持连接就要将会话停住而不能退出
如果不需要保持交互的话可以写成这样的格式:
#!/bin/expect spawn ssh root@192.168.1.100 expect { "yes/no" { send "yes\r"; exp_continue } "password" { send "centos\r" }; } expect "#" #这里的#其实就是登陆ssh后出现的那个提示符 send "useradd user1\r" send "echo 123456 | password --stdin user1\r" expect eof #结束expect
3、还可以在expect中使用变量,格式如下
#!/bin/expect set ip 192.168.1.100 set user root spawn ssh $user@$ip #让expect处理该会话,引用了变量 expect { "yes/no" { send "yes\r"; exp_continue } "password" { send "centos\r" }; }
4、还可以使用位置变量进行传参,括号内是固定格式,不用做变动,0代表第一个参数,以此类推,
#!/bin/expect set ip [lindex $argv 0] set user [lindex $argv 1] spawn ssh $user@$ip #让expect处理该会话,引用了变量 expect { "yes/no" { send "yes\r"; exp_continue } "password" { send "centos\r" }; }
5、最后使用expect执行脚本
expect expect.sh
示例:使用expect批量推送公钥
可以看到该脚本在for循环中用到了{}&这样的组合,这是使用多进程的方式在执行循环,然后使用wait等所有线程都执行完毕后进行最后的finish。使用多进程执行脚本时需要注意的是要结合命名管道(使用mkfifo命令创建命名管道)来控制进程的数量,否则执行大批量操作时会出错
#!/usr/bin/bash >ip.txt password=yourpassword rpm -q expect &>/dev/null if [ $? -ne 0 ];then yum -y install expect fi if [ ! -f ~/.ssh/id_rsa ];then ssh-keygen -P "" -f ~/.ssh/id_rsa fi for i in {1..254} do { ip=192.168.122.$i ping -c1 -W1 $ip &>/dev/null if [ $? -eq 0 ];then echo "$ip" >> ip.txt /usr/bin/expect <<-EOF set timeout 10 spawn ssh-copy-id $ip expect { "yes/no" { send "yes\r"; exp_continue } "password:" { send "$password\r" } } expect eof EOF fi }& done wait echo "finish...."
版权声明:如无特殊标注,文章均为本站原创,转载时请以链接形式注明文章出处。
评论