找回密码
 注册
查看: 3906|回复: 1

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

[复制链接]

1

主题

0

回帖

12

积分

管理员

积分
12
QQ
发表于 2017-12-22 16:37:15 | 显示全部楼层 |阅读模式
在linux下写shell脚本是非常有用的,当然,交互式shell脚本更是受到欢迎。expect的简单易用性,使它受到了大家的关注。今天在写expect脚本时遇到一个问题,下面是我对问题的理解:: H3 h' a8 k% a* z4 y4 {1 q' r
      先看下面“写法一”:
2 }& X% J  s. z6 w.........         , b3 e9 q7 I* m$ Z# M  R4 a/ ]
    expect   "A"   send "AA"
- R( h2 \; W6 R! A1 Z$ j( t, r+ x8 @    expect "B"  send "BB"- W" }5 ]7 }- `# P! u0 W
....6 f! K. u/ M- ]
刚开始,我以为程序会一个个检查,当出现expect的内容时,发送相应内容,当不出现时直接跳到下一个expect。
3 P5 x, i" _8 r  s5 q7 F; a- N+ v$ c  c. ]比如: 1.正常交互顺序 9 `% M4 |- f; Z  ?
要求输入A内容时,send "AA": H) d! U4 D% K
要求输入B内容时,send "BB". ^9 e# W/ j3 e# x& s! ^
   2.不确定的交互,有些交互在某种情况下出现,有些不出现,下面的例子将举例; \" m; v2 {0 X- l3 _' h" R
                不用输入A了,直接要求输入B内容时,send“BB”& m1 n8 M3 }- I
对于第二种情况,按我以前的理解写法一是可以的,当期望的A交互没出现而交互B出现了,会直接跳过,但事实不是这,它会阻塞,一直等到A交互出现。因此,当有些应用的脚本交互的内容不确定时,写法一将不通用。下面这个例子是我遇到的实例,写一个shell脚本实现远程登录,
8 U* O9 u3 b4 {     写法二:) E% M; M" N9 W
                 spawn ssh -l username 192.168.1.1; c! V" v$ g( n, O
          expect "(yes/no)?"  send "yes"7 t2 }5 X5 x2 y5 E
   expect "password:" send "AAAA"; u) W5 l5 H+ M; ?& }5 O9 H  H
          interact
* c$ ~1 J2 f- {! t: G         这个脚本是不行的,大家知道,第一次ssh一个远程主机时会出现yes/no的交互,当以后ssh时不会出现,而是只出现第二个,按照上述分析的原因,此脚本第一次时使用时没有问题的,以后再使用时会出现阻塞,因为它一直在等待yes/no的交互,不会跳过去。因此,如果想写一个通用的脚本,就要在交互要求不确定时,跳过一些,最终的写法如下:5 ?; S' o) n  z5 c+ E0 ~
写法三:
( `7 B. X% O, A3 s" }9 Z       spawn ssh -l username 192.168.1.1
7 c% L9 i  o% p* i6 g$ G: [expect{
/ z0 d$ _; Q" m$ b2 x- G6 w; [, |, T9 R4 n "(yes/no)?" { send "yes"; exp_continue}# ^/ J3 n! _8 G
"password:" {send "AAAA"}/ B+ v8 f% j; k7 M0 F& d
         }
, e# g, u8 n4 d" G" w) I interact
% O% G. R9 `- B, z" {5 x这里可以理解为expect块,当出现yes/no交互式当然send相应内容,当没有出现,而是出现password时也不会阻塞,而是执行相应的send。理解时可以联想case语句块。

1

主题

0

回帖

12

积分

管理员

积分
12
QQ
 楼主| 发表于 2017-12-22 17:12:25 | 显示全部楼层
echo | ssh -l root passwd --stdin
  M- o5 N, p" i" `( U8 hecho "newpass" | ssh -l root 10.11.103.151 passwd --stdin dewang
/ A9 O1 ^; F/ w# D) u3 O6 S" }root@10.11.103.151's password: 0 g1 W, N. {( t8 K8 P3 X
Changing password for user dewang.7 P( d" U5 g3 f6 j' `+ \
passwd: all authentication tokens updated successfully.0 R* `, R; p  w4 b0 p) C6 _

/ f! u( \$ V3 Z% G; p% w6 [5 \; Q% U" F! L3 `; k+ Q6 w' m2 @
#!/usr/bin/expect1 O1 B1 W' e- b5 h0 \
#@brief to change user password by ssh remote machine4 _: |. w+ j; ]- s# P

$ w8 }! a3 m% b+ \: s! G; s; f% kproc usage {funcname} {  K' l1 {3 Z3 ]% N
    puts "Usage: "
( d2 f4 D( d2 U1 D* F    puts "    $funcname -user "
9 ?9 T4 O0 r- Y2 B! u) S    puts "    $funcname -root "! Q6 \0 X% E3 m. t% m' N. Q
}   " S8 ?" g. c; w$ K# Z5 Q
) y  Y$ Q, J; Q& e
# check param
# u+ \0 s, j  E) ?7 f% a$ ]. oif { $argc != 5 } {+ C' u$ _! u7 ^
    usage $argv0 1 U3 B3 }# f- i! g6 f
    exit 1+ p2 r/ \% U5 k3 [
}) D- {  g) K: `
4 s9 l4 K  n* B5 L
# get param
  I! d7 X9 ~2 U* Y; M: hset host [lindex $argv 0]
6 T4 w. j/ M1 Y& w$ @) `set username [lindex $argv 1]& x! _" F. p0 h2 Z
set newpasswd [lindex $argv 2]
  [, v  S  Y% yset loginname "root"8 Z# r; c- M5 b! K* r6 X
if { [string compare [lindex $argv 3] "-user"] == 0 } {
! q4 ^' C/ Y. C# J6 x, Y7 ?, \: |    set loginname $username
% B2 Q6 {  f+ m/ f}2 v7 u) M8 O8 y" V/ P  |
set passwd [lindex $argv 4]
! P3 C, T0 `2 v1 y- R, ~puts "$host $username $newpasswd $loginname $passwd"
0 Q1 S4 C1 N$ n+ c1 B# l! L6 u6 V9 c9 Y7 X, R; G
spawn ssh -l $loginname $host
9 U1 K* E/ E' e! u4 X/ {5 ]expect {/ ^/ `8 l. [$ b  H8 v
"*(yes/no)*" { send "yes\r"; set sshkey 1 }
* X7 j  n- p$ W9 D  n"*assword:*" { send "$passwd\r"; set sshkey 0 }/ I1 _! z- _8 G- ^
if sshkey == 1 {7 f8 {( k/ S; K+ `- c3 p0 z: ]2 y9 }) |
    expect "*password:*"
! N. m& g8 a% u8 z; n9 f) `    send "$passwd\r"$ t  d& h/ H- m0 e: Y* m& J# ?
}
+ a; d2 l9 p4 `  s0 p$ ]1 K1 o}1 S4 R/ v- A- y! K& F
expect "*#"
/ S1 J. V! _+ B, s7 Z$ ^
# {: x: S7 j) m. ~2 lif { [string compare $loginname "root"] == 0 } {
7 ^) @, {7 J- M) [* x( P5 X& W- x0 Y3 }    #send "echo \"$username:$newpasswd\" | chpasswd\r": ^* o; w) J) s7 e( N5 u
    send "echo \"$newpasswd\" | passwd --stdin \"$username\"\r". i9 j# X) L) |. a
} else {
0 ^# \+ D  r7 [    send "passwd\r"$ o' q( q( X+ A: ]7 X
    expect {
; h; X" e1 A$ O1 ~% A  S4 b" G* \# C* H    "*current*assword:" {send "$passwd\r"}
$ f$ @  K; R# q7 k' I    "passwd: Authentication token manipulation error" {exit}  v0 j: `+ a; L3 w. T: w# `
    }
  i- f% O* Q; U$ w4 O# _2 U    expect "New*assword:"
" Q/ `! a# e- _9 K5 K1 Z1 v    send "$newpasswd\r"
  D' P3 \$ R9 l) s4 |( |% T    expect "Retype*assword:", M6 _" z  M- b3 q; s
    send "$newpasswd\r"  e7 m4 v( s3 A3 a
}
# {, {6 `: D* oexpect "*#"
2 G8 k  i5 t6 ~' y# j3 Ysend "exit\r"( C  M. C7 U5 {9 _& }
#interact 是否将交互权接过来,如果接过来,则用户这时可进行交互操作
您需要登录后才可以回帖 登录 | 注册

本版积分规则

返回首页|Archiver|手机版|小黑屋|易陆发现技术论坛 ( 蜀ICP备2026014127号-1 )

GMT+8, 2026-6-12 01:56 , Processed in 0.025895 second(s), 22 queries .

Powered by Discuz! X5.0

© 2001-2026 Discuz! Team.

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