expectとssh-agentによるマルチSSHで複数台サーバー効率管理

サーバー台数の増加による諸問題

サーバーのノード数が増えてくると、各サーバーにログインしてコマンドを実行したり、設定ファイルを変更したりする行為が大変になってきます。数台程度ならまだ良い方でしょうが、ソーシャルゲームなどでは200台を超えるサーバーを管理することなどはザラにあるので、そのような運用効率手段として、複数台にコマンドを一括適用できるマルチSSHのシャルスクリプトがあると便利です。

SSH公開鍵認証とssh-agent

まず、SSHの秘密鍵と公開鍵を作成して各対象サーバーに配布します(鍵の作成や配布に関してはここでは省略します)。SSHの秘密鍵は、ノンパスで作成すると流出したら大変なことになりますので、パスワードありで設定しましょう。その後、接続元のbash_profileとbash_logoutにssh-agentの設定をします(これでログイン時に1回パスワードが聞かれて、それ以降は各サーバーにログインする際に毎回パスワードを入力しなくてもすむようになります。ssh-agentが秘密鍵のパスワードを記録してくれるのです)

ssh-agentの有効化

ssh-agentを有効化するために、接続元のbash_profileに以下の設定を入れましょう。

eval `ssh-agent`
ssh-add

次に、ログアウト時にssh-agentも終了するように、shell_logoutを編集します。

ssh-agent -k

以上でssh-agent設定は完了です。

expectによるシェルスクリプトの作成

最初に、expectをインストールしましょう。

$ sudo yum install -y expect

その後、comman.shというシェルスクリプトを作成しましょう。expectというコマンドを使います。シェルスクリプトは以下のように記述してください。

#!/usr/bin/expect

set timeout 5
spawn ssh [lindex $argv 0]
expect "Last login"
send [lindex $argv 1]\n
send exit\n
interact

#!/bin/bashではなく、#!/usr/bin/expectである点にご注意ください。実行権限を付けておきましょう。

次に、コマンドを適用したい対象サーバーを列挙したシェルスクリプトを作ります。ここではmulti_ssh.shというファイル名にします。

#!/bin/bash

array=("192.168.1.1" "192.168.1.2" "192.168.1.3" "192.168.1.4" "192.168.1.5" "192.168.1.6" "192.168.1.7" "192.168.1.8" "192.168.1.9" "192.168.1.10")

for (( i = 0; i &< ${#array[*]}; i++ ))
{
./cmmand.sh "${array[i]}" "$1"
}

これで完成です。./multi_ssh.sh “ls -al”と実行すると、対象サーバーのファイルリストが見られるはずです。

うまく動かない時は

対象サーバーに公開鍵が登録されているか、ssh-agentが接続元サーバーで稼働しているかを確認しましょう。

応用例

$ ./multi_ssh "yum install -y httpd"

で全台にApacheをインストール。

$ ./multi_ssh "df -m"

で、サーバー全台のディスク使用量を調査。他にも色々な使い方ができます。

expectおまけ

expectは対話的な作業も実行することができます。例えば最初にあった公開鍵を各サーバーにばら撒くような作業も、以下のようなシェルで実行できます。

#!/usr/bin/expect

set timeout 5
spawn ssh [lindex $argv 0]
expect "password:"
send "*************\r"
send "rsync -e \"ssh -o 'UserKnownHostsFile=/dev/null' -o 'StrictHostKeyChecking=no'\" -avz 192.168.1.1:/root/.ssh /root\n"
expect "root@192.168.1.1's password:"
send "*************\n"
expect "receiving incremental file list"
expect "sent"
expect "total"
send "exit\r"
interact

最初、シェルスクリプトを作るのが若干面倒ですが、マルチSSHが出来るようになるとサーバーの作業効率が格段に向上します。ぜひお試し頂ければと思います。