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

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

[复制链接]

1

主题

0

回帖

12

积分

管理员

积分
12
QQ
发表于 2017-12-22 16:37:15 | 显示全部楼层 |阅读模式
在linux下写shell脚本是非常有用的,当然,交互式shell脚本更是受到欢迎。expect的简单易用性,使它受到了大家的关注。今天在写expect脚本时遇到一个问题,下面是我对问题的理解:# ?; G- [5 D' }2 R# {
      先看下面“写法一”:
' P; {" V" k2 R% s) h.........         $ W) J) `$ u# Y4 X' D
    expect   "A"   send "AA"2 }  \. e, T1 `( q9 w1 A$ A2 Q
    expect "B"  send "BB", S* L1 c9 ?' A# Y' w
....
* E: @4 S. u+ r1 }" ]: }刚开始,我以为程序会一个个检查,当出现expect的内容时,发送相应内容,当不出现时直接跳到下一个expect。$ ]6 y2 O! [" h# m0 _5 n
比如: 1.正常交互顺序
3 r( ^! Y! e1 N/ O6 T& V要求输入A内容时,send "AA"5 P: c/ K; @% S% |
要求输入B内容时,send "BB"0 ]8 A: g3 ?/ [# v" @
   2.不确定的交互,有些交互在某种情况下出现,有些不出现,下面的例子将举例
7 U( {# A7 F0 u% `7 L, }                不用输入A了,直接要求输入B内容时,send“BB”
9 w/ D; d( `2 D( z: O  q" y对于第二种情况,按我以前的理解写法一是可以的,当期望的A交互没出现而交互B出现了,会直接跳过,但事实不是这,它会阻塞,一直等到A交互出现。因此,当有些应用的脚本交互的内容不确定时,写法一将不通用。下面这个例子是我遇到的实例,写一个shell脚本实现远程登录,4 Z0 M8 B/ B* E$ G2 f$ \( g7 ]
     写法二:
3 F5 e; [: }, R                 spawn ssh -l username 192.168.1.1
' \+ O2 z" @" e8 t! i          expect "(yes/no)?"  send "yes"& A. q9 B6 a5 f( u0 a& c+ D
   expect "password:" send "AAAA"
* z" {/ i3 N2 G7 S' A0 c% e& Q# Q: q0 b          interact
! O+ R. N6 R: H2 y         这个脚本是不行的,大家知道,第一次ssh一个远程主机时会出现yes/no的交互,当以后ssh时不会出现,而是只出现第二个,按照上述分析的原因,此脚本第一次时使用时没有问题的,以后再使用时会出现阻塞,因为它一直在等待yes/no的交互,不会跳过去。因此,如果想写一个通用的脚本,就要在交互要求不确定时,跳过一些,最终的写法如下:; I% z  D, ]/ d$ Y* P
写法三:
0 a' w0 t4 W( L5 Q( Y6 M       spawn ssh -l username 192.168.1.1
2 t1 K$ Y, M7 M; g9 F( H8 l/ W) m; Dexpect{
2 V+ Z# }6 D4 r! \! k "(yes/no)?" { send "yes"; exp_continue}
; P4 c& @6 I0 f# Q" y5 J "password:" {send "AAAA"}3 O% w  {& y4 H2 L" G. {$ n
         }
. F7 t/ Y6 S; _' P5 K, ~ interact+ Z' Z( m0 X8 ^4 r
这里可以理解为expect块,当出现yes/no交互式当然send相应内容,当没有出现,而是出现password时也不会阻塞,而是执行相应的send。理解时可以联想case语句块。

1

主题

0

回帖

12

积分

管理员

积分
12
QQ
 楼主| 发表于 2017-12-22 17:12:25 | 显示全部楼层
echo | ssh -l root passwd --stdin4 {0 d( a8 P0 \7 l
echo "newpass" | ssh -l root 10.11.103.151 passwd --stdin dewang
: y2 {. U1 S7 Q& Y3 C3 ~; ?root@10.11.103.151's password:
" Q6 I/ v& ~  z; [( y% ]4 aChanging password for user dewang.+ Q; o7 q! C5 h4 `5 t4 g
passwd: all authentication tokens updated successfully.
" _& j  ~  @/ z# j' K! u
. d. j" @+ T2 v; R( X; B$ m
- X0 g5 e0 H) `- f. F+ ?#!/usr/bin/expect) f! V  Z/ o* E5 w: H. F! X
#@brief to change user password by ssh remote machine! X" k# c( d" g+ Z

) R1 Y7 Z/ l8 S' k: v% x7 z" pproc usage {funcname} {
; n$ l6 E# k* M; U( d9 ^  L5 K, u    puts "Usage: "
0 b. p. `* P7 z; `; d. [/ i    puts "    $funcname -user "
- d) d; |) K$ h8 _3 m& D- J* m! @* h    puts "    $funcname -root "
; I$ J, B* P* E7 J9 Q& [) `}   $ a* M  Q! l; j  ~/ p+ d
. f7 S8 r1 C) X, d- [' }
# check param- n3 T# ^' k6 b. i: V5 E7 _# F
if { $argc != 5 } {* U  U1 m1 D) _# A; Q5 a
    usage $argv0 3 h: Q9 \: O6 C% u0 Y
    exit 1) J, F5 j+ J4 A8 K8 P9 v: O
}
+ s" _' E6 {/ f. g3 Y7 @8 p& x8 M9 W; J! u0 ]1 r* R! i
# get param
9 L: s' ^! z" q" v" O3 e/ W6 rset host [lindex $argv 0]
' J: e5 B% l' |. S9 x7 ^  Iset username [lindex $argv 1]
& ^+ a9 H& o2 A7 o" Iset newpasswd [lindex $argv 2]1 i& Z* M# V! s
set loginname "root"
. Z0 u( }  n3 c* `+ rif { [string compare [lindex $argv 3] "-user"] == 0 } {: v# |; v: F* o0 ^* h3 x  V- ^8 k, I- ?
    set loginname $username
% W4 p7 @4 H: q1 j; e/ K}
( \5 s  _& o0 K3 k( O$ U" }# g$ q5 {set passwd [lindex $argv 4]
+ D+ q0 F  h( d  U; E  k8 w1 xputs "$host $username $newpasswd $loginname $passwd"  h: h( u* ~! h

3 P) f' U9 Z) i8 xspawn ssh -l $loginname $host/ c* F" j, S2 D; h  i
expect {
# t4 K8 s% V- C6 z' s1 @"*(yes/no)*" { send "yes\r"; set sshkey 1 }
/ e- k- w9 j1 X* `7 y+ F5 H"*assword:*" { send "$passwd\r"; set sshkey 0 }7 I) ^& i, g2 F9 i0 n  W5 Y. Z
if sshkey == 1 {
. t, L# Z, |& j8 v4 Z( q    expect "*password:*"
0 S# Z0 L) z; i4 `8 K; A2 j3 x    send "$passwd\r"; _1 m: T. P2 ~4 V8 m
}
. v1 C/ A/ L8 b, u! ~}
) K& y: ^: @: d5 G% W3 k; texpect "*#"
: ~* T$ e/ a& j# \: m; d4 B$ N8 r& L. \. ?+ l5 _
if { [string compare $loginname "root"] == 0 } {9 |( @4 H7 ?, X/ Y$ c( }. j7 u
    #send "echo \"$username:$newpasswd\" | chpasswd\r"- K0 x$ l) X4 ]9 N
    send "echo \"$newpasswd\" | passwd --stdin \"$username\"\r"1 R* H$ o% t, W* x& Q+ I8 G) m
} else {
; y, ?" e% e) ?9 {/ k& Y* Z    send "passwd\r"9 c+ y/ `& v1 B" e: q) Z  B' G
    expect {
, S& g) d6 k+ D: d8 j4 M: F    "*current*assword:" {send "$passwd\r"}1 J8 G" J  C# J- `
    "passwd: Authentication token manipulation error" {exit}
8 }3 c1 W" m* Z, }: A    }
2 Z" M8 a. O! _6 A4 h    expect "New*assword:"
6 j6 e$ a0 q- ]5 p3 L    send "$newpasswd\r"& f3 N, H5 Z1 R' `+ n# u6 W
    expect "Retype*assword:"
! d1 i9 q9 n2 v, L) X    send "$newpasswd\r"
! D! |6 r# D  h( ?! r* Z/ D* h4 g}
2 m: a9 o  s+ v( l+ @expect "*#"( N! z* R# e7 U: {+ ]
send "exit\r"
1 A& d! t& j% W: u#interact 是否将交互权接过来,如果接过来,则用户这时可进行交互操作
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2026-6-12 05:33 , Processed in 0.017081 second(s), 21 queries .

Powered by Discuz! X5.0

© 2001-2026 Discuz! Team.

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