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

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

[复制链接]

1

主题

0

回帖

12

积分

管理员

积分
12
QQ
发表于 2017-12-22 16:37:15 | 显示全部楼层 |阅读模式
在linux下写shell脚本是非常有用的,当然,交互式shell脚本更是受到欢迎。expect的简单易用性,使它受到了大家的关注。今天在写expect脚本时遇到一个问题,下面是我对问题的理解:( j9 t% k( E- Q: A
      先看下面“写法一”:4 x1 [. o  h! o0 E/ p
.........         
/ z3 K( k$ O0 O7 M5 a" I9 |: T: q    expect   "A"   send "AA"
+ H2 t; t& _, h. y' H' @: f( p    expect "B"  send "BB"
% W: P% @6 A% m( V. T8 @$ _....
4 q# |) G2 v2 {9 k+ J, p. ~" `- i刚开始,我以为程序会一个个检查,当出现expect的内容时,发送相应内容,当不出现时直接跳到下一个expect。
) S* Z- ~2 i2 ^/ A0 s8 c# R3 b$ G比如: 1.正常交互顺序
6 `/ Q: v8 U# o! l+ l% X- D要求输入A内容时,send "AA"
8 m( s9 y* c: j5 B! x要求输入B内容时,send "BB"
5 o  z7 j. F3 g' Q   2.不确定的交互,有些交互在某种情况下出现,有些不出现,下面的例子将举例
; B( p6 l- _; t                不用输入A了,直接要求输入B内容时,send“BB”; T3 e* k+ d9 r3 }. V# x- p5 K
对于第二种情况,按我以前的理解写法一是可以的,当期望的A交互没出现而交互B出现了,会直接跳过,但事实不是这,它会阻塞,一直等到A交互出现。因此,当有些应用的脚本交互的内容不确定时,写法一将不通用。下面这个例子是我遇到的实例,写一个shell脚本实现远程登录,& R; t5 q. b7 b, Y) e( b7 p
     写法二:0 c2 }9 L8 a  s. S% m
                 spawn ssh -l username 192.168.1.1
) F5 D' H/ b: a  B( S' N. N! V          expect "(yes/no)?"  send "yes"" K0 ]& S# z6 B. _0 e: w
   expect "password:" send "AAAA"+ y4 x4 |, f2 O4 [6 k5 r& {
          interact
9 e3 n9 @  L& k4 M         这个脚本是不行的,大家知道,第一次ssh一个远程主机时会出现yes/no的交互,当以后ssh时不会出现,而是只出现第二个,按照上述分析的原因,此脚本第一次时使用时没有问题的,以后再使用时会出现阻塞,因为它一直在等待yes/no的交互,不会跳过去。因此,如果想写一个通用的脚本,就要在交互要求不确定时,跳过一些,最终的写法如下:
/ L9 ]; l" P9 y$ n写法三:5 K0 f4 N9 B) w- h
       spawn ssh -l username 192.168.1.1- C$ `7 u: p2 l5 A0 V
expect{
: j) v. S5 H6 }1 L# [1 ^* q9 m$ _% \ "(yes/no)?" { send "yes"; exp_continue}
7 O4 n! V5 D3 n# O( D, u8 Q- y2 J "password:" {send "AAAA"}4 N, ?" s6 I) n/ o( b& t4 s
         }
$ F7 ^: a* X6 L1 P7 w! ]! ? interact
5 ?/ ]5 }" _1 f# H  h这里可以理解为expect块,当出现yes/no交互式当然send相应内容,当没有出现,而是出现password时也不会阻塞,而是执行相应的send。理解时可以联想case语句块。

1

主题

0

回帖

12

积分

管理员

积分
12
QQ
 楼主| 发表于 2017-12-22 17:12:25 | 显示全部楼层
echo | ssh -l root passwd --stdin5 D$ V  o! G+ X& O1 |
echo "newpass" | ssh -l root 10.11.103.151 passwd --stdin dewang
; Z# m3 M0 k3 N* S8 v! _/ Zroot@10.11.103.151's password:
7 s" x; ~) T* p' I0 f1 }) EChanging password for user dewang.
( `) p% \1 T; U5 q% \passwd: all authentication tokens updated successfully.# k7 k; [5 J1 o$ L, Q
. ^) T* g' D6 Y7 V' D
% L0 R/ Q5 U3 b* S2 u% I
#!/usr/bin/expect9 ?) |! D6 Z4 I2 y2 B
#@brief to change user password by ssh remote machine9 Q! ~9 o& Z' |

% m" [- J' \" w0 @3 [proc usage {funcname} {
+ i( t4 E" p8 T3 z* L    puts "Usage: "9 A! V) m* W" F5 }
    puts "    $funcname -user "
( c0 o8 g3 E6 {    puts "    $funcname -root "
( Y: Q- t$ V9 d1 Q; a. x; F}   1 \9 c& ]: I  _5 [5 J% k" b

3 m$ Q4 `$ W( e$ B7 i3 t# check param7 U) F& S4 R$ I. |
if { $argc != 5 } {! _7 g9 n3 J% J2 n8 X6 a" e: s
    usage $argv0
! N. H6 u7 X7 K7 ~; J    exit 1
2 L' i) k! _; r0 Y  p; R/ K/ X}
3 V4 a9 K( x$ X1 H
- v/ H6 m$ U* J+ {: n. p# get param
; c  y6 ^) t" }5 d& o+ b9 jset host [lindex $argv 0]
5 p% u/ ]8 {7 Iset username [lindex $argv 1]+ g. ]* u8 g$ E/ j/ a$ k
set newpasswd [lindex $argv 2]1 ^* C) _+ A/ r: h1 m1 m
set loginname "root"  k  e5 X) m, m: I" o5 x' \
if { [string compare [lindex $argv 3] "-user"] == 0 } {1 R  l( `( \3 ?' F. T
    set loginname $username" I4 m2 n( s  i
}4 r, D0 F7 S" C7 m6 ?
set passwd [lindex $argv 4]3 q+ E8 X3 w: b5 S
puts "$host $username $newpasswd $loginname $passwd"
2 [9 L6 I5 V8 h' h
) @$ |, k0 i- b/ i) s/ ^spawn ssh -l $loginname $host
/ z: k& {, \! ?! P5 e4 L0 f9 iexpect {# _. c; _$ z! f0 U$ ?1 y# @
"*(yes/no)*" { send "yes\r"; set sshkey 1 }
+ |! m$ [* x8 W% {% D8 B"*assword:*" { send "$passwd\r"; set sshkey 0 }  K( u9 s# r; v& X: b5 O3 s
if sshkey == 1 {
1 ~9 U( t& D9 N    expect "*password:*"
& m% n4 v4 X6 X# X$ n0 U# S  D    send "$passwd\r"
) J' |; j: Y& G}
* ^" ~& k2 Q* v8 v# e! a}
, Y5 `; e' ^& P# H6 g6 D; N" L6 Uexpect "*#"
5 w+ H; F5 W+ Y
4 j& R- e0 i# n" _& `3 N6 ?if { [string compare $loginname "root"] == 0 } {
, Y2 T, t3 ?4 M' ^9 \    #send "echo \"$username:$newpasswd\" | chpasswd\r"
+ V3 F, M( Q1 N7 N; z3 A    send "echo \"$newpasswd\" | passwd --stdin \"$username\"\r"1 N5 J; l8 z0 d
} else {& f% j, A$ f2 J
    send "passwd\r"9 k! w8 p9 ^; Z$ P: q
    expect {( {% b: y8 R8 N3 ~4 \! w& z
    "*current*assword:" {send "$passwd\r"}+ T/ R2 a. N- H% k* h
    "passwd: Authentication token manipulation error" {exit}
/ {1 {! s# g! h+ K    }
' K' A0 }; o4 ?# K; J% q4 G    expect "New*assword:"+ |( F$ |( t. n1 u5 H
    send "$newpasswd\r", a$ s, c# m" q4 x1 c. ?
    expect "Retype*assword:"% }1 t5 w4 `: I6 E9 k( {+ h1 G' u" U
    send "$newpasswd\r"
& C7 m, q$ O9 V' d. l- z}
0 m3 j4 \6 c6 L+ R$ D$ G# Z4 c" {expect "*#"
3 Q8 |: _+ b' T+ {6 fsend "exit\r"
8 c6 g% }4 d. }' i& T: l#interact 是否将交互权接过来,如果接过来,则用户这时可进行交互操作
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2026-6-12 03:21 , Processed in 0.021899 second(s), 22 queries .

Powered by Discuz! X5.0

© 2001-2026 Discuz! Team.

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