热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

linux脚本之expect【机器交互】

Expect是一个免费的编程工具语言;expect是在上的一个自动化交互套件,主要应用于执行命令和程序时,系统以交互形式要求输入指定字符串,实现交互通信。shell和expect理

一、expect初探

       expect是一个免费的编程工具语言;expect是在Linux系统上的一个自动化交互套件,主要应用于执行命令和程序,系统以交互形式要求输入指定字符串,实现交互通信。shell和expect理解为两种不同的脚本语言,expect有独自的语法、变量


二、expect自动交互流程

1、spawn启动指定进程---expect获取指定关键字---send向指定程序发送指定字符---执行完成退出.


2、注意该脚本能够执行的前提是安装了expect


    yum install -y expect

    3、expect常用命令总结:

      lspawn              交互程序开始后面跟命令或者指定程序
      lexpect 获取匹配信息匹配成功则执行expect后面的程序动作
      lsend exp_send 用于发送指定的字符串信息
      lexp_continue 在expect中多次匹配就需要用到
      lsend_user 用来打印输出 相当于shell中的echo
      lexit               退出expect脚本
      leof expect执行结束 退出
      lset 定义变量
      lputs 输出变量
      lset timeout        设置超时时间




      三.脚本案例

      1、ssh登录远程主机执行命令,执行方法 expect 1.sh 或者 ./1.sh



        # vim 1.sh
        #!/usr/bin/expect
        spawn ssh saneri@192.168.21.13 df -Th
        expect "*password"
        send "yc1256\n"
        expect eof



        2、ssh远程登录主机执行命令,在shell脚本中执行expect命令,执行方法sh 2.sh、bash 2.sh 或./2.sh都可以执行.


          #!/bin/bash
          passwd='123456'


          /usr/bin/expect <<-eof
          set time 30
          spawn ssh saneri@192.168.56.103 df -Th
          expect {
          "*yes/no" { send "yes\r"; exp_continue }
          "*password:" { send "$passwd\r" }
          }
          expect eof
          EOF



          3.expect执行多条命令



            #!/usr/bin/expect -f


            set timeout 10


            spawn sudo su - root
            expect "*password*"
            send "123456\r"
            expect "#*"
            send "ls\r"
            expect "#*"
            send "df -Th\r"
            send "exit\r"
            expect eof


            4. 创建ssh key,将id_rsa和id_rsa.pub文件分发到各台主机上面。


            4.1、创建主机配置文件


              [root@localhost script]# cat host
              192.168.1.10 root 123456
              192.168.1.20 root 123456
              192.168.1.30 root 123456
              [root@localhost script]# ls
              copykey.sh hosts


              4.2、编写copykey.sh脚本,自动生成密钥并分发key.


                [root@localhost script]# vim copykey.sh
                #!/bin/bash
                # 判断id_rsa密钥文件是否存在
                if [ ! -f ~/.ssh/id_rsa ];then
                ssh-keygen -t rsa -P "" -f ~/.ssh/id_rsa
                else
                echo "id_rsa has created ..."
                fi
                #分发到各个节点,这里分发到host文件中的主机中.



                  while read line
                  do
                  user=`echo $line | cut -d " " -f 2`
                  ip=`echo $line | cut -d " " -f 1`
                  passwd=`echo $line | cut -d " " -f 3`
                    
                  expect <
                  set timeout 10
                  spawn ssh-copy-id $user@$ip
                  expect {
                  "yes/no" { send "yes\n";exp_continue }
                  "password" { send "$passwd\n" }
                  }
                  expect "password" { send "$passwd\n" }
                  EOF
                  done


                  5、shell调用expect执行多行命令.



                    #!/bin/bash
                    ip=$1
                    user=$2
                    password=$3
                    expect <
                    set timeout 10
                    spawn ssh $user@$ip
                    expect {
                    "yes/no" { send "yes\n";exp_continue }
                    "password" { send "$password\n" }
                    }
                    expect "]#" { send "useradd hehe\n" }
                    expect "]#" { send "touch tmp/test.txt\n" }
                    expect "]#" { send "exit\n" } expect eof
                    EOF
                    #./ssh5.sh 192.168.1.10 root 123456


                     6、使用普通用户登录远程主机,并通过sudo到root权限,通过for循环批量在远程主机执行命令.


                      $ cat timeout_login.txt
                      10.0.1.8
                      10.0.1.34
                      10.0.1.88
                      10.0.1.76
                      10.0.1.2
                      10.0.1.3


                      #!/bin/bash
                      for i in `cat home/admin/timeout_login.txt`
                      do
                      usr/bin/expect <
                      spawn usr/bin/ssh -t -p 22022 admin@$i "sudo su -"




                      expect {
                      "yes/no" { send "yes\r" }
                      }




                      expect {
                      "password:" { send "xxo1#qaz\r" }
                      }


                      expect {
                      "*password*:" { send "xx1#qaz\r" }
                      }




                      expect "*]#"
                      send "df -Th\r"
                      expect "*]#"
                      send "exit\r"
                          expect eof
                      EOF
                      done

                      7、 密码过期需要批量修改密码

                        #!/bin/bash


                        for i in `cat root/soft/ip.txt`
                        do




                        usr/bin/expect <
                        spawn usr/bin/ssh root@$i
                            expect {
                        "UNIX password" { send "Huawei@123\r" }
                        }


                        expect {
                        "New password:" { send "xxHuzzawexxi@1234#\r" }
                        }




                        expect {
                        "Retype new password:" { send "xxHuzzawexxi@1234#\r" }
                        }




                        expect "*]#"
                        send "echo Huawei@123|passwd --stdin root\r"
                        expect "*]#"
                        send "exit\r"
                        expect eof
                        EOF
                        Done



                        四、expect 注意事项

                        1、expect 和 send 交互式执行

                              在服务器上测试过的语句,最后得出结论是spawn开启的新进程,后面的expect和send都是在和这个进程打交道,如果再重新开启一个spawn会自动退出上一个进程,然后重新开启。【比如我在图中spawn连接了远程服务器,执行一些语句,然后再开启一个spawn,那么第二个spawn会在本地运行,因为他们不属于同一个进程了。还有一点是,开启了spawn的进程中,输入send 发送交互语句的时候 在后面必须有一个expect,spawn 命令是出现交互式的前提下的  但是expect 匹配不上的话,那么它就会按照timeout 的设置进行等待




                          #!/usr/bin/expect
                          2
                          3 set timeout 30
                          4 spawn ssh 10.192.224.224
                          5 expect "password:"
                          6 send "mypassword\n"
                          7 expect "*$"


                                上面这个例子中send "mkdir tmpdir\n" #远程执行命令用send发送,不用spawn, expect "*$" #注意这个地方,要与操作系统上环境变量相匹配,尤其是有空格的情况下,一定在expct "*$ "把空格加上,加不上你就完蛋了。我试过。这个例子实际上是通过ssh 去登录远程机器,并且在远程机器上创建一个目录, 我们看到在我们输入密码后并没有去expect eof,这是因为ssh 这个spawn 并没 有结束,而且手动操作时ssh 实际上也不会自己结束除非你exit;所以你只能 expect bash 的提示符,当然也可以是机器名等,这样才可以在远程创建一个目 录。注意,请不要用spawn mkdir tmpdir,这样会使得上一个spawn 即ssh 结束,那 么你的tmpdir 将在本机建立。当然实际情况下可能会要你确认ssh key,可以通过并行的expect 进行处理,不 多赘述。


                          2、添加变量,send 中的语句执行必须要expect


                            #!/usr/bin/expect


                            set timeout 10
                            set host [lindex $argv 0]
                            set username [lindex $argv 1]
                            set password [lindex $argv 2]
                            set src_file [lindex $argv 3]
                            set dest_file [lindex $argv 4]


                            spawn scp $src_file $username@$host:$dest_file
                            expect {
                            "(yes/no)?"
                            {
                            send "yes\n"
                            expect "*assword:" { send "$password\n"}
                            }
                            "*assword:"
                            {
                            send "$password\n"
                            }
                            }
                            expect "100%"

                               expect eof



                              2.1、注意代码刚开始的第一行,指定了expect的路径,与shell脚本相同,这一句指定了程序在执行时到哪里去寻找相应的启动程序。

                              2.2、代码刚开始还设定了timeout的时间为10秒,如果在执行scp任务时遇到了代码中没有指定的异常,则在等待10秒后该脚本的执行会自动终止。

                              2.3、spawn代表在本地终端执行的语句,在该语句开始执行后,expect开始捕获终端的输出信息,然后做出对应的操作。

                              2.4、expect代码中的捕获的(yes/no)内容用于完成第一次访问目标主机时保存密钥的操作。有了这一句,scp的任务减少了中断的情况。代码结尾的expect eof与spawn对应,表示捕获终端输出信息的终止。有了这段expect的代码,还只能完成对单个远程主机的scp任务。

                              2.5、如果需要实现批量scp的任务,则需要再写一个shell脚本来调用这个expect脚本。


                              3、expect 编写过程中空格请用“tab”键代替

                              4、当你执行expect脚本send一条命令的时候,会触发一次匹配动作—————》这个特性导致当你的命令中存在要匹配的关键字时,命令不会执行,而是永远能够匹配,进而影响预期执行效果!该特性通过执行expect -d打印debug信息能够观察到(可以通过清除缓存避免该问题)

                              5、多条send命令会并行执行,如果要串行,最好一条send一条expect

                              6、timeout和eof应该对应的是某个expect,也就是说,每个expect模块都应该设置timeout或eof响应行为

                              7、eof:当spawn新起的线程终止时(可以模拟kill即可),接受到eof信号,触发当前expect中的eof,把eof定义到全局是错误的行为,会报can not find channal named.

                              8、scp等执行完就结束的进程,可以直接通过捕获eof来判断是否执行完成

                              在多条件匹配时(一个expect里面多个表达式),expect会丢弃已经匹配的文本(或者说会在已经匹配到的文本末尾打个标记),当exp_continue再次进入时,会从标记位置往后继续匹配。也就是说,匹配的不是$expect_out(buffer)

                              9、注意,如果远程主机密码中有“$”、“#”这类特殊字符的话,在编写列表文件时就需要在这些特殊字符前加上转义字符,否则expect在执行时会输入错误的密码。


                              日常疑问:

                              1、免费软件和开源软件区别

                              开源软件:指公开源代码的软件。开源软件在发行的时候会附上软件的源代码,并授权允许用户更改、传播或者二次开发。

                              免费软件:免费提供给用户使用的软件,在免费的同时,通常也会有一些限制,比如源代码不公开,用户不能随意修改、不能二次发布等。






                              推荐阅读
                              • 本文介绍了在mac环境下使用nginx配置nodejs代理服务器的步骤,包括安装nginx、创建目录和文件、配置代理的域名和日志记录等。 ... [详细]
                              • 本文介绍了5个基本Linux命令行工具的现代化替代品,包括du、top和ncdu。这些替代品在功能上进行了改进,提高了可用性,并且适用于现代化系统。其中,ncdu是du的替代品,它提供了与du类似的结果,但在一个基于curses的交互式界面中,重点关注占用磁盘空间较多的目录。 ... [详细]
                              • 安装mysqlclient失败解决办法
                                本文介绍了在MAC系统中,使用django使用mysql数据库报错的解决办法。通过源码安装mysqlclient或将mysql_config添加到系统环境变量中,可以解决安装mysqlclient失败的问题。同时,还介绍了查看mysql安装路径和使配置文件生效的方法。 ... [详细]
                              • 本文介绍了在rhel5.5操作系统下搭建网关+LAMP+postfix+dhcp的步骤和配置方法。通过配置dhcp自动分配ip、实现外网访问公司网站、内网收发邮件、内网上网以及SNAT转换等功能。详细介绍了安装dhcp和配置相关文件的步骤,并提供了相关的命令和配置示例。 ... [详细]
                              • 本文讨论了在Windows 8上安装gvim中插件时出现的错误加载问题。作者将EasyMotion插件放在了正确的位置,但加载时却出现了错误。作者提供了下载链接和之前放置插件的位置,并列出了出现的错误信息。 ... [详细]
                              • 在CentOS/RHEL 7/6,Fedora 27/26/25上安装JAVA 9的步骤和方法
                                本文介绍了在CentOS/RHEL 7/6,Fedora 27/26/25上安装JAVA 9的详细步骤和方法。首先需要下载最新的Java SE Development Kit 9发行版,然后按照给出的Shell命令行方式进行安装。详细的步骤和方法请参考正文内容。 ... [详细]
                              • 树莓派语音控制的配置方法和步骤
                                本文介绍了在树莓派上实现语音控制的配置方法和步骤。首先感谢博主Eoman的帮助,文章参考了他的内容。树莓派的配置需要通过sudo raspi-config进行,然后使用Eoman的控制方法,即安装wiringPi库并编写控制引脚的脚本。具体的安装步骤和脚本编写方法在文章中详细介绍。 ... [详细]
                              • 本文介绍了在MacOS系统上安装MySQL的步骤,并详细说明了如何设置MySQL服务的开机启动和如何修改MySQL的密码。通过下载MySQL的macos版本并按照提示一步一步安装,在系统偏好设置中可以找到MySQL的图标进行设置。同时,还介绍了通过终端命令来修改MySQL的密码的具体操作步骤。 ... [详细]
                              • 安装oracle软件1创建用户组、用户和目录bjdb节点下:[rootnode1]#groupadd-g200oinstall[rootnode1]#groupad ... [详细]
                              • 我无法续订几天前过期的RHELDeveloper帐户订阅。我执行了以下步骤,但是,订 ... [详细]
                              • Ansibleplaybook roles安装redis实例(学习笔记二十九)
                                1、相关redis参数:2、templatesredis.conf配置相关参数:daemonizeyespidfilevarrunredis_{{red ... [详细]
                              • 本文主要介绍关于linux文件描述符设置,centos7设置文件句柄数,centos7查看进程数的知识点,对【Linux之进程数和句柄数】和【linux句柄数含义】有兴趣的朋友可以看下由【东城绝神】投 ... [详细]
                              • MySQL5.6.40在CentOS764下安装过程 ... [详细]
                              • 基于SSL的mysql服务器的主从架构实现说明:本文选用172.16.22.1作为主服务器,172.16.22.3作为从服务器从服务器的mysql软件版 ... [详细]
                              • 【爬虫】关于企业信用信息公示系统加速乐最新反爬虫机制
                                ( ̄▽ ̄)~又得半夜修仙了,作为一个爬虫小白,花了3天时间写好的程序,才跑了一个月目标网站就更新了,是有点悲催,还是要只有一天的时间重构。升级后网站的层次结构并没有太多变化,表面上 ... [详细]
                              author-avatar
                              淘宝_韩版女装铺
                              这个家伙很懒,什么也没留下!
                              PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
                              Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有