Shell 和 Expect 脚本的自动登录运行

来源:互联网 发布:ps for mac下载 编辑:程序博客网 时间:2024/05/18 02:42

先转2篇文章

http://www.ibm.com/developerworks/cn/linux/l-cn-firmupgrade/

 

http://www.ibm.com/developerworks/cn/aix/library/0909_jinjh_unixlogin/

 

 

编写 Shell 和 Expect 脚本

关于 Expect 脚本

现代的 Shell 对程序提供了最小限度的控制 ( 开始,停止,等等 ),而把交互的特性留给了用户。这意味着有些程序,用户不能非交互的运行,比如说 passwd。Expect 恰恰填补了这个缺陷,解决了在 Unix 环境中长期存在着的一些问题。

Expect 使用 Tcl 作为语言核心。不仅如此,不管程序是交互和还是非交互的,Expect 都能运用。一个 Expect 程序员可以写一个脚本来描述程序和用户的对话。接着 Expect 程序可以非交互的运行“交互式”的程序。写交互式程序的脚本和写非交互式程序的脚本一样简单。

这样,像 telnet, su, rlogin, ftp 等应用如果没有一个用户接口交互式的提供输入,Shell 脚本根本无法自动执行下去。Expect 脚本则可以做到。

Expect 语言是基于 Tcl 的。Tcl 实际上是一个子程序库,这些子程序库可以嵌入到程序里从而提供语言服务。最终的语言有点象一个典型的 Shell 语言,并可以被嵌套在 Shell 脚本中使用。

Expect 脚本使用 spawn 命令激活一个 Unix 程序来进行交互式运行;使用 send 命令向进程发送字符串;使用 expect 命令等待进程的某些字符串;也可以像 Shell 脚本一样使用 set 命令给变量赋值;控制程序执行的 if, for, continue 等命令,还能进行普通的数学和字符串操作。

因此,可以使用 Expect 脚本来完成对 AMM 的 telnet 中的一些交互性操作。

准备工作

首选确认是否安装了如下 rpm 包,如果没有安装,请安装

 rpm -q expect  expect-5.42.1-1 

根据上一章节的执行流程,需编写三个脚本,分别为:

run.sh 执行整个程序流程

remotechassis.tcl 发现网络里所有的 AMM 的 IP 地址

update.tcl AMM 固件的升级

编写 run.sh 的脚本

run.sh 用来执行整个程序过程,其中涉及到要使用 telnet 连接到 AMM 中执行相应的控制命令,因此我们使用两个 Expect 脚本来分别完成发现网络里所有的 AMM 的 IP 地址和让 AMM 执行固件升级的功能。

由于需要升级固件的 AMM 有多个,可以在 run.sh 中加入循环来自动完成多个 AMM 固件的升级,并将升级进程放入后台运行,这样可以同时执行多个升级进程。

为了保证所有 AMM 固件升级完成,设定延迟 1200 秒后,将所有升级进程 kill 掉。

下面是 run.sh 脚本的具体内容


清单 1. run.sh 代码

 #!/bin/sh  # 指 定 登 录 到 其 中 一 个 AMM 中 ,执 行 发 现 remotechassis.tcl 脚 本 , 发  # 现 网 络 中 所 有 的 AMM IP 地 址 ,并 格 式 化 记 录 到 IP.out 文 件 中 ./remotechassis.tcl 192.168.1.125 USERID PASSW0RD |grep IP: |cut -c17- >ip.out  # 读 取 ip.out 文 件 中 的 每 一 行 AMM 的 IP 地 址, 然后执行 update.tcl 进  # 行 后 台 升 级  for eachline in `cat ip.out` ;do  # 执行 update 升级脚本,并放入后台执行 ./update.tcl $eachline USERID PASSW0RD &  done  # 延 迟 20 分 钟 , 结 束 所 有 的 update.tcl 进 程 sleep 1200  killall update.tcl 

编写 remotechassis.tcl 脚本:

要发现网络里面的 AMM,可以执行 AMM 中的

 remotechassis – T mm[1] 

命令来完成。给 telnet 中需要的 IP 地址、用户名和密码三个变量赋值,然后开始请求 telnet 访问,成功之后,执行 remotechassis – T mm[1] 命令让其发现网络里面 AMM 的 IP 地址。run.sh 会调用此脚本执行后的输出,格式化后记录到 ip.out 文件中。

remotechassis.tcl 脚本具体内容如下:


清单 2. remotechassis.tcl 代码

 #!/usr/bin/expect  # 设定 timeout 指为 -1,让 expect 永远等待输入 set timeout -1  # 设定输入提示 if { $argc != 3 } {     puts "Usage $argv0 hostname userid password"    exit 1  }  # 设定 telnet AMM 的三个变量 set host [lindex $argv 0]  set user [lindex $argv 1]  set pass [lindex $argv 2]  # 执行 telnet 命令,并将 ip 地址传递给 telent  spawn telnet $host    expect *name:     # 等待用户名输入 send  "$user/r"   # 发送用户名字符串 expect *assword:  # 等待密码输入 send "$pass/r"    # 发送密码字符串 expect system>  # 发送 remotechassis 命令 send " remotechassis -T mm/[1/]/r" expect system>  # 发送 exit 命令退出 telent  send "exit/r" expect eof 

编写 update.tcl 脚本:

要让 AMM 执行固件升级命令,需要执行 AMM 中的

 update – r – u tftp://tftp_ip/firmware_filename – T mm[1] 

这样的命令来完成。给 telnet 中需要的 IP 地址、用户名和密码三个变量赋值,然后开始请求 telnet 访问,成功之后,执行上述升级命令。run.sh 会读取 ip.out 中每个 AMM 的 IP 地址,并循环调用此脚本来实现多个 AMM 并行升级。

update.tcl 脚本具体内容如下:


清单 3. update.tcl 代码

 #!/usr/bin/expect  # 设定 timeout 指为 -1,让 expect 永远等待输入 set timeout -1  if { $argc != 3 } {     puts "Usage $argv0 hostname userid password"    exit 1  }  set host [lindex $argv 0]  set user [lindex $argv 1]  set pass [lindex $argv 2]  spawn  telnet $host  expect *username  send "$user/r" expect *assword:  send "$pass/r" expect system>  # 发送 update 命令开始升级 AMM 的固件 # 需 要 指 定 tftp 服 务 器 地 址 和 AMM 固 件 的 升 级 文 件 名 send "update -r -u tftp://192.168.19.3/CNETCMUS.pkt -T mm/[1/]/r" send "exit/r" expect eof 

再贴最后的代码:

 

 

  1 servers="10.144.23.45 10.144.23.46 10.144.23.52 10.144.23.59 10.144.23.60 10.144.23.61 10.144.23.62 10.144.23.63 10.144.23.64 10.144.23.65 10.144.23.66 10.144.23.67 10.144.23.68 10.144.23.69"
      2 #servers="10.144.23.45"
      3
      4 for server in $servers
      5 do
      6     ./kill-memcached.exp $server
      7 done
      8
      9 for server in $servers
     10 do
     11     ./start-memcached.exp $server
     12 done
     13
     14 counter=0
     15 for server in $servers
     16 do
     17     serverEnd=`echo $server | awk '{print substr($0,length($0)-1,2)}'`
     18     echo "./memSet.exp $server $counter $serverEnd &"
     19     ./memSet.exp $server $counter $serverEnd &
     20     sleep 10
     21     counter=`expr $counter + 1`
     22 done
     23
     24 wait
     25 exit
     26


       1 #!/usr/bin/expect
      2
      3 set timeout -1 这个很关键,之前自动退出就是因为没有设超时时间
      4 set server [lindex $argv 0]
      5 set sNum [lindex $argv 1]
      6 set serverEnd [lindex $argv 2]
      7 spawn ssh -p 36000 -l username $server
      8 expect "username's password:"
      9 #sleep 1
     10 send "username/r"
     11 expect "*>"
     12 send "cd memcache/r"
     13 expect "*>"
     14 send "./memSetAll.sh $sNum/r"
     15 expect "$serverEnd:~/memcache>"   这一行是技巧,使之找到应有的行,说明已经介绍 且与其他行区分
     16 #send "exit/r"
     17 expect eof

原创粉丝点击