Cygwin 上でのシリアル端末エミュレータと expect

例えばネットワークの変更作業を終えた後にもろもろのステータスを確認するログを取得するときなど、大量の機器に対しお決まりの一連のコマンドを投入したいときがあります。 そんなとき私の周囲の人々は Tera Term のマクロを駆使してコマンドラインインターフェイス上での一連のコマンド実行を自動化するわけですが、 私はいまさら Tera Term のマクロを覚えるよりは手許にある expect のスクリプトをちょっと直して済ませたいと思ってしまうわけです。 マクロの類など使わずに、実行するコマンドを羅列したテキストエディタから端末エミュレータへコピー&ペーストするという手もありますが、 このやり方を取ると一般に機器の応答を待たず一連のテキストをペーストしてしまうので、何かの拍子にペーストしたコマンドがきちんと認識されずエラーが起こるというのはありがちなことです。 そもそもコピペの連続などエンジニアの作業としてはどうなのかという問題 (?) もあります。

さて、expect を使いたい時は Cygwin の expect を使います。ネットワーク越しにアクセスできれば /usr/bin/telnet.exe を使ってログインをした後に機器のコマンド実行をするスクリプトを作って流すことができます。 しかし、もろもろの理由でシリアルケーブルを使ってコマンド実行しなければならない時もあります。 Tera Term ならばネットワーク接続でもシリアル接続でもどちらでも問題ないのですが、expect を使うときは telnet の代わりにシリアル端末エミュレータを使わなければなりません。 「シリアル端末エミュレータ」という言葉はかなりニッチな分野でコレという決定的なソフトが無いように思います。 ですので選択が難しいところですが、私の場合は jerm を使っています。

何故 jerm だったのかは記憶が定かでないのですが、とりあえずコンパイルして使っていて問題がないのでそのまま使い続けています。 ただし、コンパイルにはそれなりにソースを修正しています。 jerm-8095 用のパッチファイルはこちらです。 そのうち blog で取り上げようと思いつつコンパイルをしたのが既に1年以上前になってしまい、詳細は覚えていないのですが、 今その内容を見ると苦労してコンパイルした後が窺えます。 単純にシリアルターミナルエミュレータとして動かすことのみを目的としたパッチファイルですので、他の付加機能がきちんと動くかは試していませんのでご注意ください。 getaddrinfo-1.6.3.tar.gz を利用させていただきましたが、これはパッチファイルの中に含まれています。

さて expect を使ったコマンドの実行例です。 とりあえず、サンプルレベルですが、以下が expect スクリプトと実行するネットワーク機器のコマンドファイル (Cisco Catalyst 用) の例です。enable 用パスワードは cisco としています。また、COM2 (=/dev/ttyS1) を利用しています。 見てお分かりのように、シリアル通信を開始してプロンプトを出し enable する手順を、 while 文を用いてプログラム化しています。

docmd.exp

set timeout 2
match_max 100000
if {[llength $argv]>0} {
set filename [lindex $argv 0]
set enablep "cisco"
set fp [open $filename r]
set pid [spawn /usr/local/bin/jerm -r xnrn /dev/ttyS1]
set done ""
while {"$done" == ""} {
expect {
">" {
set timeout -1
send -- "enable\r"
expect "Password: "
send -- "$enablep\r"
}
"#" {
set done 1
}
timeout {
send -- "\r"
}
}
}
while {![eof $fp]} {
set cmd [gets $fp]
send -- "$cmd\r"
expect "#"
}
send -- "exit\r"
exec kill $pid
close $fp
close
}

status.cmd

terminal length 0
show clock
show interface
show route
show logging

この2つを用いて以下のように実行すれば、status.log に実行結果を残すことができます。

expect docmd.exp status.cmd | tee status.log

expect を使うとシェルスクリプトと組み合わせて複数の機器にパラメータを調整しながら telnet でコマンド実行したりということも書きやすいので、 重宝しています。 というかそのような用途に Tera Term のマクロより expect + sh スクリプトを選ぶ私が嗜好が今の時代だと特殊かも知れませんが。 expect についての情報は多くないのですが、Tcl の拡張なので文法は Tcl について調べればオッケーです。


2007. 8. 10 追記
コメント欄にある通り、 jerm 作者の方が、パッチの内容を取り込んだ新バージョンをリリースしてくださいました。 バイナリ版も合わせてリリースされていますので、Cygwin でシリアル通信プログラムを探している方はまず jerm を試してみてはいかがでしょう?

2011. 7. 29 追記
少し前perl の expect モジュールを見つけました。 私のように tcl よりは perl の方が嬉しいという人はチェックしてみてください。