易陆发现互联网技术论坛

 找回密码
 开始注册
查看: 3905|回复: 1
收起左侧

用expect写交互式shell脚本之expect 执行顺序

[复制链接]
发表于 2017-12-22 16:37:15 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?开始注册

x
在linux下写shell脚本是非常有用的,当然,交互式shell脚本更是受到欢迎。expect的简单易用性,使它受到了大家的关注。今天在写expect脚本时遇到一个问题,下面是我对问题的理解:
# ?: m8 J: v, s9 t      先看下面“写法一”:
2 X- C# R. K6 Y.........         
8 c  h7 V: f  o$ a  X% s; S    expect   "A"   send "AA"
) H8 y) i* W/ X& k( e$ u    expect "B"  send "BB"+ d* x* f" r$ i
....9 H% ~. R7 c; j* {( X
刚开始,我以为程序会一个个检查,当出现expect的内容时,发送相应内容,当不出现时直接跳到下一个expect。
1 M& u% A0 W, y$ i3 V, b/ J& A/ s比如: 1.正常交互顺序 ) S( P) ~* \& O2 L0 P
要求输入A内容时,send "AA"+ p- M& n$ O( e
要求输入B内容时,send "BB"; [* B1 ^/ N" x; D! _6 K
   2.不确定的交互,有些交互在某种情况下出现,有些不出现,下面的例子将举例
, [  A0 h% {" C2 }7 Z                不用输入A了,直接要求输入B内容时,send“BB”
* u0 Z' Z( H) [5 _对于第二种情况,按我以前的理解写法一是可以的,当期望的A交互没出现而交互B出现了,会直接跳过,但事实不是这,它会阻塞,一直等到A交互出现。因此,当有些应用的脚本交互的内容不确定时,写法一将不通用。下面这个例子是我遇到的实例,写一个shell脚本实现远程登录,3 [2 m6 a, `  b. D: `( x" R
     写法二:4 O0 ?4 U: t* W; l5 Q( ^/ J
                 spawn ssh -l username 192.168.1.1
" }4 ^( T2 z9 l9 p          expect "(yes/no)?"  send "yes"
3 O7 f. J: K; |% ?8 K   expect "password:" send "AAAA"7 l7 `; n5 h- i, R3 _3 {; @$ @
          interact
  w: K. k; |" \( }         这个脚本是不行的,大家知道,第一次ssh一个远程主机时会出现yes/no的交互,当以后ssh时不会出现,而是只出现第二个,按照上述分析的原因,此脚本第一次时使用时没有问题的,以后再使用时会出现阻塞,因为它一直在等待yes/no的交互,不会跳过去。因此,如果想写一个通用的脚本,就要在交互要求不确定时,跳过一些,最终的写法如下:
3 I- b- k/ G, T, p写法三:
. `- P% Q" Z. ]1 G& H( t       spawn ssh -l username 192.168.1.10 H- ~2 E7 S. ?# Z$ J  p
expect{3 t9 j+ l% y; ~4 Z, ~+ \7 T
"(yes/no)?" { send "yes"; exp_continue}, ]8 z" x% e# B+ G
"password:" {send "AAAA"}1 ~2 j' p' Y& j: E: p
         }
6 r" [. O3 E; T8 I' ^+ Q% l( \ interact
6 n; O4 {) O1 t7 q* ?" l3 B这里可以理解为expect块,当出现yes/no交互式当然send相应内容,当没有出现,而是出现password时也不会阻塞,而是执行相应的send。理解时可以联想case语句块。
 楼主| 发表于 2017-12-22 17:12:25 | 显示全部楼层
echo | ssh -l root passwd --stdin" Z' ~7 W( @- E- s5 d. n2 c
echo "newpass" | ssh -l root 10.11.103.151 passwd --stdin dewang
/ }2 j9 x) r2 H7 n2 h& jroot@10.11.103.151's password:
: \1 e8 M$ Q# S- Z. v. M1 FChanging password for user dewang.
) F* k  R$ Z9 H; vpasswd: all authentication tokens updated successfully.
7 ?9 n7 d; j+ \* ]4 x( x3 s) Y/ I- _% q" R4 A1 D8 E" J# M& L( d# Y
/ u7 o; ^# v( u0 V, k# ]
#!/usr/bin/expect
) K% m1 S; u( w: e) C# m$ R& P#@brief to change user password by ssh remote machine
# M' B, v6 U' n' K* d# R0 O
* ?; ]3 D- Q' W4 Lproc usage {funcname} {8 J8 O5 R  J: z) P9 a
    puts "Usage: "! }0 U' D, n; N! K3 M
    puts "    $funcname -user "+ c( f1 W4 B7 p
    puts "    $funcname -root "
. G4 B: z' u& s}   
" @; Q) Z3 \" Q: b& X/ M2 Q
$ n! o+ R( u, x' T; u. S. I# check param
! @  q0 F8 ~! Iif { $argc != 5 } {
  H* D0 U; y# [8 c+ C0 S    usage $argv0 , I/ V8 I) h/ B' Z. N' p# {
    exit 1$ o+ e0 A+ a1 c0 y; @
}4 l- z- A8 f$ k' A8 s' N8 U
& ?& n9 G: I' S' D" z$ f' x. c. U
# get param
* |: ^$ Q& U- H' ^* N8 L% D- p/ Tset host [lindex $argv 0]
5 m$ ^& |6 |0 u! |$ _set username [lindex $argv 1]8 s. ~, N6 G+ u7 v* Y
set newpasswd [lindex $argv 2]$ Y* ]& O! Z2 N2 c
set loginname "root"
( ?8 n2 H" H" s$ R# sif { [string compare [lindex $argv 3] "-user"] == 0 } {
/ v) [/ t) e- y) f% H7 z/ @/ P    set loginname $username! G7 v0 u# V' _" O3 G: y" X
}. \& A  L" O+ B8 s! ?" i
set passwd [lindex $argv 4]$ q9 m/ h, k+ I$ e' f% j5 Y0 U7 P
puts "$host $username $newpasswd $loginname $passwd": M" M' b6 p/ P. ]! a1 N$ r1 |
+ T. {8 T5 o$ j3 ^
spawn ssh -l $loginname $host* [4 L* _: I, |' n" K1 ?0 D
expect {
, v& n. a% d0 W" t"*(yes/no)*" { send "yes\r"; set sshkey 1 }
# @: z) X* D- o! p"*assword:*" { send "$passwd\r"; set sshkey 0 }
* S; y2 l- a, H* L  zif sshkey == 1 {5 [- }* }! P$ V, H
    expect "*password:*"1 Q' d9 E" }& p; |- n7 M- G; ?# {
    send "$passwd\r"
8 g0 a0 t" b; m' F* F9 }6 k}
' l7 t. u2 u. e7 F3 k  _}
! ^6 T) H, ^+ t6 e& t3 i2 Yexpect "*#"
. U: I% q5 A2 T
  g8 t% c5 i2 [6 X' H  Cif { [string compare $loginname "root"] == 0 } {
" Z# K# W) o! Y0 C8 Y$ j, r1 ^9 e    #send "echo \"$username:$newpasswd\" | chpasswd\r"
+ w+ ?8 D! p$ a3 H4 E7 L6 g8 H    send "echo \"$newpasswd\" | passwd --stdin \"$username\"\r"
" i- _- ?( a! G( W} else {
) R- ], F8 R8 K' q6 g    send "passwd\r"2 r  ~" F2 _+ V1 h7 ]. T1 U! @0 v0 ?
    expect {: g- ?% H# ^! m4 C% a
    "*current*assword:" {send "$passwd\r"}
) l9 P, @7 E- w* m, ^7 w2 \+ m5 e6 ?    "passwd: Authentication token manipulation error" {exit}
$ i3 h; a" k3 U8 U    }! Y7 c% N* I4 ?0 o: o' i; F- Q
    expect "New*assword:"9 v; ^& [& X3 h
    send "$newpasswd\r"
5 x0 v! J: Y! H& l6 R4 p    expect "Retype*assword:"
# D/ j2 B0 V' c/ W* ~    send "$newpasswd\r"+ c( `* C1 F2 n) r
}
. ~7 {" y) G/ L$ z+ |  F3 Zexpect "*#"
( K1 `% D( B" \5 X4 E4 R" Z' o# Tsend "exit\r"
+ r* k' n' @( x& `( D  A2 T0 U#interact 是否将交互权接过来,如果接过来,则用户这时可进行交互操作
您需要登录后才可以回帖 登录 | 开始注册

本版积分规则

关闭

站长推荐上一条 /4 下一条

北京云银创陇科技有限公司以云计算运维,代码开发

QQ|返回首页|Archiver|小黑屋|易陆发现技术论坛 ( 蜀ICP备2026014127号-1 )点击这里给我发消息

GMT+8, 2026-4-9 01:10 , Processed in 0.042838 second(s), 22 queries .

Powered by Discuz! X3.4 Licensed

© 2012-2025 Discuz! Team.

快速回复 返回顶部 返回列表