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);
}