試される大地から

furaiboが送る技術ブログ。プログラミングのTipsなど書いていきます。

expectコマンドが便利

最近、sshでのリモートログインや、パッケージインストール・設定変更といった一連の作業の自動化を行う機会があった。この際にexpectコマンドが大活躍したので、その使い方についてメモしておこうと思う。

expectコマンドのインストール方法

インストールは非常に簡単である。インストールは
CentOS(Redhat系)とUbuntu(Debian系)の場合を次に示す。

CentOSの場合
yum -y install expect
Ubuntuの場合
apt-get -y install expect



expectコマンドの利用例

expectコマンドは/usr/bin/にインストールされる。
もしも、expectコマンドしか使わない場合ならばシバン行は#!/usr/bin/expectと指定する。

まずは、自分のLinuxがインストールされたPC上でroot権限に入る場合を考える。

CentOS(日本語環境)の場合
#!/usr/bin/expect
respawn su
expect "パスワード"
send "[あなたのrootパスワード]\n"
Ubuntu(日本語環境)の場合
#!/usr/bin/expect
respawn sudo su
expect "パスワード"
send "[あなたのrootパスワード]\n"


[あなたのrootパスワード]の部分には、実際のパスワードの文字列が入るものと考えて欲しい。
実際のパスワードがmypasswordであれば、

send "mypassword\n"

となる。


expectコマンドを利用する際、「respawn [シェルのコマンド]」とすると、シェルのコマンドを実行できる。
例えば、

respawn ls

とすると、lsコマンドが自動で実行できるし、

respawn su

とすれば、suコマンドが自動で実行できることになる。
さらに、「expect "[特定の文字列]"」とすることで、特定の出力に対応できる。
「send "[送りたいコマンドor文字列]\n"」はexpectで指定した文字列が現れた場合の対応を行う。
Enterを押したことは\nにより表現する。

つまり、

expect "パスワード"
send "[あなたのrootパスワード]\n"

とすることは、「パスワード」という文字列が出現した時に、rootパスワードを入力し、エンターキーを押すことと同じとなるのである。


expectコマンドの応用例

これまで説明した知識を利用してexpectコマンドを使って、あるサーバにsshでリモートログイン(root権限)し、gitをインストール後にログアウトする処理を記述してみる。Ubuntuの場合は、設定を変更していない限りrootではログイン出来ないため、一度ユーザアカウントでログインする。

ログイン先サーバがCentOSの場合
#!/usr/bin/expect
respawn ssh [サーバのドメイン or IPアドレス] -l root
expect "Are you sure you want to continue connecting (yes/no)?"
send "yes\n"
expect "password"
send "[サーバのrootパスワード]\n"
expect "#"
send "yum -y install git\n"
expect "#"
send "exit"
ログイン先サーバがUbuntuの場合
#!/usr/bin/expect
respawn ssh [サーバのドメイン or IPアドレス] -l [あなたのアカウント名]
expect "Are you sure you want to continue connecting (yes/no)?"
send "yes\n"
expect "password"
send "[あなたのアカウントのパスワード]\n"
expect "$"
send "sudo su\n"
expect "password"
send "[サーバのrootパスワード]\n"
expect "#"
send "apt-get -y install git"
expect "#"
send "exit"
expect "$"
send "exit"



もしも初回のリモートログインであれば、「Are you sure you want to continue connecting (yes/no)?」という表示が出るはずであるので、これに対応する必要がある。また、root権限に入った場合、シェルには

[(サーバ名)@root]# 

という表示が出るはずであるので、「expect "#"」という記述はこれに対応したものとなる。
ここで、もしも、普通のシェルスクリプトにexpectコマンドを交ぜ書きしたい場合には次のようになる。

#!/bin/sh

expect -c "
respawn ssh [サーバのドメイン or IPアドレス] -l root
expect \"Are you sure you want to continue connecting (yes/no)?\"
send \"yes\\n\"
expect \"password\"
send \"[サーバのrootパスワード]\\n\"
expect \"#\"
send \"yum -y install git\\n\"
expect \"#\"
send \"exit\"
"