LoginSignup
0
0

More than 1 year has passed since last update.

expect と spawn のサブルーチン化

Posted at

expect のメモ

expect は、LANスイッチやサーバなどに自動接続してアレコレするのに便利なスクリプト。

expect の基本形

以下、ssh で接続して接続先で適当なコマンドを発行する例。
spawn して expect, send の繰り返しのため、サブルーチン化したい。

sample1.ex
#!/usr/bin/expect
set timeout 5
spawn env LANG=C ssh user@192.168.0.10
expect "assword:" { send "userpass\r" } 
expect "\\\$"
send "echo hello\r"      ; # 任意のコマンド実行例1
expect "\\\$"
send "pwd\r"             ; # 任意のコマンド実行例2
interact

expectとsend をサブルーチン化(-> OK)

spawn 後の expect と send は基本的に対で実行するため、proc で
サブルーチン化すると連続したコマンド発行を(見た目)簡素化できる。

sample2.ex
#!/usr/bin/expect
set timeout 5

proc SENDS { data } {  ; # <---- サブルーチン化
  expect "\\\$"
  send "$data\r"
}

spawn env LANG=C ssh user@192.168.0.10
expect "assword:" { send "userpass\r" } 

SENDS "echo hello"   
SENDS "pwd"          
interact
結果
$ ./sample2.ex
spawn env LANG=C ssh user@192.168.0.10
user@192.168.0.10's password: 
Last login: Sun Jan 29 01:53:32 2023 from mypc
$ echo hello
hello
$ pwd
/home/user

spawn をサブルーチン化(-> NG)

上記の例に続けて、spawn もサブルーチン化すると期待通りの動作をしない。
expect -d で見ると、spawn_proc の spawn で生成されたプロセスID である spawn_id が
spawn_proc 外で参照できない局所的な値のためらしい。

sample3.ex
#!/usr/bin/expect
set timeout 5

proc SENDS { data } {
  expect "\\\$"
  send "$data\r"
}

proc spawn_proc { } {  ; # <---- サブルーチン化
  spawn env LANG=C ssh user@192.168.0.10
  expect "assword:" { send "userpass\r" } 
  SENDS "echo hello"   
  SENDS "pwd"          
  interact
}
spawn_proc             ; # <---- spawn 呼び出し
結果
$ ./sample3.ex
spawn env LANG=C ssh user@192.168.0.10
user@192.168.0.10's password: echo hello  <---sendが正しく動作していない
Last login: Sun Jan 29 01:59:16 2023 from mypc

spawn_id を send に渡す(-> OK)

spawn_id を別のサブルーチンに引数で渡し、受けた側は expect -isend -i で使う。

sample4.ex
#!/usr/bin/expect
set timeout 5

proc SENDS { sid data } { ; # <---- 引数で受け取る
  expect -i $sid "\\\$"   ; # <---- -i オプション
  send -i $sid "$data\r"  ; # <---- -i オプション
}

proc spawn_proc { } {
  spawn env LANG=C ssh user@192.168.0.10
  expect "assword:" { send "userpass\r" } 
  SENDS $spawn_id "echo hello"   ; # <---- 引数で渡す
  SENDS $spawn_id "pwd"          ; # <---- 引数で渡す
  interact
}
spawn_proc          

これは期待動作する。

spawn_id を global 宣言する(-> OK)

spawn をサブルーチン化する proc で global spawn_id する。

sample5.ex
#!/usr/bin/expect
set timeout 5

proc SENDS { data } {
  expect "\\\$"
  send "$data\r"
}

proc spawn_proc { } {
  global spawn_id      ; # <---- 追加
  spawn env LANG=C ssh user@192.168.0.10
  expect "assword:" { send "userpass\r" } 
  SENDS "echo hello"  
  SENDS "pwd"
  interact
}
spawn_proc

同じく動作する。SENDS 側は global spanw_id しなくていい。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0