複数サーバでコマンドやスクリプトを一括実行したい><
というときのメモ書きと自作スクリプトの紹介。
事前に『SSHでパスワードなしログイン & sudo』の設定が完了してる前提です。
※セキュリティや作業ミス時の影響範囲などを十分に考慮する必要があります。
シェルでベタ打ち
シェルでfor文、while文書くのを苦にしない人はこれで充分でしょう
$ for i in site1-app0{1..3};do echo "[$i]";ssh $i 'sudo crontab -l';done
$ cat site1-app.list | while read l;do echo "[$l]";ssh -n $l 'sudo crontab -l';done
ツールを使う
コマンド一括実行ツールもいろいろあります
capistranoはRailsのデプロイなどに使われるツールですが、独自タスクを定義すればけっこうなんでもできちゃいますし、複数台に対する擬似的なシェルが使えたり、もちろんコマンド実行もできたりします。
これらのツールは各サーバで並列にコマンドやタスクを実行できるため、サーバ台数が多いときに非常に高速でオペレーションを実施できます。
※tomahawkはまだ使ったことないので今度試してみる
ちょっと便利に作業するためのスクリプト作ってみた
対象サーバの管理とスクリプトの実行機能が欲しかったので、3つのスクリプトを作ってみました
タグを指定してサーバのリストを出力するスクリプト
[mikeda@admin work]$ cat list/all_servers site1-app01 site1,app site1-app02 site1,app site1-app03 site1,app,standby site1-db01 site1,db site1-db02 site1,db test01 test,app,mail ... [mikeda@admin work]$ ./print_sv site1 app site1-app01 site1-app02 site1-app03
まとめてコマンドを実行するスクリプト
[mikeda@admin work]$ ./print_sv site1 app | ./ssh_run_cmd hostname [site1-app01] site1-app01 [site1-app02] site1-app02 [site1-app03] site1-app03
まとめてスクリプトを実行するスクリプト
まず実行したい処理をスクリプトで記述します。
例)apacheコンフィグをSubversionからアップデートしてgracefulするスクリプト
#!/bin/sh -x sudo svn up /etc/httpd/conf /etc/httpd/conf.d sudo /etc/init.d/httpd configtest && sudo /etc/init.d/httpd graceful
まとめて実行
$ ./print_sv site1 app | ./ssh_run_task task/apache_config_update.sh [site1-app01] + sudo svn up /etc/httpd/ A /etc/httpd/conf/httpd.conf リビジョン 2 に更新しました。 リビジョン 2 です。 + sudo /etc/init.d/httpd configtest Syntax OK + sudo /etc/init.d/httpd graceful [site1-app02] + sudo svn up /etc/httpd/ A /etc/httpd/conf/httpd.conf リビジョン 2 に更新しました。 リビジョン 2 です。 + sudo /etc/init.d/httpd configtest Syntax OK + sudo /etc/init.d/httpd graceful [site1-app03] + sudo svn up /etc/httpd/ A /etc/httpd/conf/httpd.conf リビジョン 2 に更新しました。 リビジョン 2 です。 + sudo /etc/init.d/httpd configtest Syntax OK + sudo /etc/init.d/httpd graceful
実運用ではテスト用のサーバで事前に動作確認したほうがいいでしょう
[mikeda@admin work]$ echo site1-app03 | ./ssh_run_task task/httpd_config_update.sh [mikeda@admin work]$ ./print_sv site1 app | grep -v site1-app03 | ./ssh_run_task task/apache_config_update.sh
ソースコード
print_sv
#!/usr/bin/perl use strict; use warnings; my @tags = @ARGV; open my $fh, "<", "list/all_servers"; while(<$fh>){ next if /^\s*#/; chomp; my ($hostname, $sv_tags) = split; if($sv_tags){ my @sv_tags = split ',', $sv_tags; print "$hostname\n" if check_tags(\@tags, \@sv_tags); } } close $fh; sub check_tags { my ($tags, $sv_tags) = @_; my %check; $check{$_} = 0 for @$tags; for(@$sv_tags){ $check{$_} = 1 if exists $check{$_}; } return ! scalar(grep {$_ == 0} values %check); }
ssh_run_cmd
#!/bin/bash sleep_time=1 while read host;do echo "[$host]" ssh -n $host "$@" echo sleep $sleep_time done
ssh_run_task
#!/bin/bash sleep_time=1 script=$1 shift remote_path=/tmp/`basename $script` while read host;do echo "[$host]" scp -q $script $host:$remote_path ssh -n $host "chmod u+x $remote_path; $remote_path $@; /bin/rm $remote_path" sleep $sleep_time echo done
sleep入れてるのはビビリだからです!
(スリープ中にCtrl+C押すと全部止められます。)
大量の手順書のスクリプト化、効率的な運用を模索中!