expect内でループ処理をする。

Linux等のリモートサーバ上で自動的に処理をさせたい場合、expectを使うのが一般的です。
今回はexpectを使って、リモートサーバ側でwhileを使った処理をさせた時のメモです。
今回やりたかったことは、サーバAからサーバBにログインし、複数ノードにPingを打つ、というような処理です。

expectの構文はtcl文法

今までよく知らずに使っていましたが、expectはtcl文法を使っていたので、下記の書式でループを作ることができました。

while { 条件式 } {
    処理
}

例) sshで入ったサーバから、192.168.1.0-128のノードにPingを打って抜ける。
こんな感じで出来ました。

#!/bin/bash

SSHHOST=hoge001
password="hogehoge"
PINGHOST="192.168.1."

expect -c "
    spawn ssh -l root $SSHHOST
    expect \"password:\" {
    send \"$password\n\"
    } \"Are you sure you want to continue connecting (yes/no)?\" {
    send \"yes\n\"
    expect \"password:\"
    send \"$password\n\"
    }
 
    set i 0
    while {\$i <= 128} {
        send \"sleep 1\n\"
        expect \"\[$username@$hostname ~\]$\"
        send \"/bin/ping -c $PINGHOST\$i\n\"
        expect \"\[$username@$hostname ~\]$\"
        incr i 1
    }

    send \"sleep 1\n\"
    expect \"\[$username@$hostname ~\]$\"
    send \"exit\n\"

    interact
"

ハマったところ

expect内で定義した変数(上記の例では"i")は、変数を使う時、事前にバックスラッシュ or 円記号を付けないとダメでした。
expect外で定義した変数は"$username"といった形で呼び出せます。

expect内で定義した変数は \$変数名 とする。

i => \$i

expect外で定義した変数は $変数名 でOK。

username => $username