« 2006年12月 | メイン | 2007年03月 »

2007年02月17日

デブサミ2007の発表資料 Nagiosのプラグインの話

2月14日のデブサミの「出張Shibuyaイベント」でLTしてきました。

内容は、Nagiosのプラグインを作成する話と、nrpeの簡単な説明です。

発表資料:nagios.pdf

プラグインを作る時には、exit時のステータスコードだけ気にすればいいので、
監視したいものがちょっと複雑なもの、例えばWWW::Mechanizeでログインしてほげほげするとかいう時でも難しくない。当たり前だけどPerlじゃなくても全然おk。

そういえば、Nagiosって個人で使う機会あまりないですよね。
発表資料を作成するときに、自宅サーバ(CentOS)にyumでインストールしてみましたが、監視するものがないので起動すらしていません。
強いて言えば、femoかもしれないけど、femoのサーバが落ちるより自宅の回線が落ちる回数の方が多いというオチになりそう。自宅のWiiとかテレビを監視するかなw

2007年02月13日

同じコマンドを複数のサーバで実行

Assurerにシェルモードが追加されたので、もういいかなという感じですが、自分の使っているスクリプトをさらしてみる。

sshで1つのコマンドを複数のサーバに順番に実行させていけます。
「password:」のプロンプトに対して、expectを使って自動で入力する機能もあるので、sudoなどにも対応

mssh -f list.txt -u user -p -- id


-f ファイル名: ホスト名が書いてあるファイル名。1行1ホスト
-u ユーザ名: ログインするユーザ名
-p: パスワードを使うフラグ
--: これ以降にコマンド
 
以下ソース

#!/usr/bin/perl

package MSH;

use strict;
use warnings;
use Expect;

sub new {
    my $class = shift;
    bless {@_}, $class;
}

sub log {
    my $self = shift;
    $self->{_log} && print @_;
}

sub execute {
    my $self = shift;
    my @cmd  = @_;

    my $user = $self->{user} || die;
    my $host = $self->{host} || die;
    my $pass = $self->{pass};
    my $cmd = join " ", @cmd;
    $cmd or die;

    $self->{_log} = 1;
    $self->log(<<EOF);
[$user\@$host] CMD: $cmd
EOF

    my @t = qw(ssh);
    push @t, "-l", $user, $host, @cmd;

    my $ssh = Expect->spawn(@t)
      || die "Warning: ssh failed on $host\n";
    $ssh->log_stdout(0);
    $ssh->log_file( sub { $self->log(shift) } );

    $ssh->expect(
        180,
        [
            qr/assword:\s*$/ =>
              sub {
                  $self->log("\n");
                  $self->{_log} = 0;
                  $ssh->send("$pass\n");
                  exp_continue;
              }
        ],
        [
            qr/.+/ =>
              sub {
                  $self->{_log} = 1;
                  exp_continue;
              }
        ],
        [
            timeout => 
              sub {
                  die "timeout.\n"
              }
        ],
    );
    $ssh->hard_close();
    print "\n";
}

1;

package main;

use strict;
use warnings;
use IO::Prompt;
use Getopt::Long;

GetOptions(
    'f=s'      => \my $list,
    'u|user=s' => \my $user,
    'p'        => \my $with_passwd,
);

my @args = @ARGV;
@ARGV=();

my $passwd;
if ( $with_passwd ) {
    $passwd = prompt("$user password: ", -echo=>"*");
    $passwd or die;
}

open(my $fh, $list);
my @hosts = <$fh>;

foreach my $host ( @hosts ) {
    chomp $host;chomp $host;

    my $msh = MSH->new(
        host => $host,
        user => $user,
        pass => $passwd
    );
    $msh->execute(@args);
}