App-rcmd
view release on metacpan - search on metacpan
view release on metacpan or search on metacpan
#!/usr/bin/perl -s
# ABSTRACT: execute a (built-in) command on remote hosts over SSH
# PODNAME: rcmd
use strict;
use warnings;
#use lib "$ENV{HOME}/perl5/lib";
use Net::OpenSSH;
use Term::ANSIColor qw(:constants);
# command line options
our ($h, $v, $l, $u, $k);
# help message
my $desc = <<"EOF";
Execute a command on remote hosts over SSH. FILE is a file containing hostnames
or IP addresses of remote hosts. Use - instead of FILE to get hosts from the
STDIN. COMMAND is either supplied by you (ex. 'df -h | grep /home') or it's one
of the built-in commands.
EOF
my $usage = <<"EOF";
$0 [-u=USER -k=KEY -v] FILE 'COMMAND'
$0 -l [-v]
$0 -h
-u=USER SSH username; default is the current username
-k=KEY SSH private key; ex. /home/foo/.ssh/id_rsa
-v be more verbose
-l list built-in commands and exit
-h print help and exit
EOF
# print help and exit
if ($h) {
print "$desc\n$usage";
exit;
}
my $private_key_path = $k || "";
# put built-in commands into a hash
my %Builtins;
while (<DATA>) {
my ($name, $cmd) = split ' ', $_, 2;
next unless $name; # skip empty lines in data
$Builtins{$name} = $cmd;
}
# list built-in commands and exit
if ($l) {
for my $name (sort keys %Builtins) {
if ($v) { # verbose
print GREEN, "$name", RESET, " --> $Builtins{$name}";
} else { # just names
print "$name\n";
}
}
exit;
}
# check and get command line arguments
@ARGV == 2 or die $usage;
my ( $hosts, $cmd ) = @ARGV;
my $contents = do { local ( @ARGV, $/ ) = $hosts; <> };
my @hosts = split ' ', $contents;
# username to use for ssh connections
my $user;
if ($u) {
$user = $u;
} else {
$user = getlogin || getpwuid($<) || die "Can't get current username";
}
# multiple connections are established (in parallel)
my %ssh;
for my $host (@hosts) {
$ssh{$host} = Net::OpenSSH->new(
$host,
user => $user,
key_path => $private_key_path,
async => 1,
timeout => 3,
master_stderr_discard => 1, # don't show the MOTD
);
}
# run a command on all the hosts (sequentially) ...
for my $host (@hosts) {
# if the supplied command is a name of a built-in command run that one
$cmd = $Builtins{$cmd} if exists $Builtins{$cmd};
my $msg = "## $host";
$msg .= ": $cmd" if $v;
print GREEN, "$msg\n", RESET;
$ssh{$host}->system($cmd);
}
=pod
=encoding UTF-8
=head1 NAME
rcmd - execute a (built-in) command on remote hosts over SSH
=head1 VERSION
version 0.005
=head1 SYNOPSIS
run "rcmd -h" to get help
=head1 AUTHOR
Jozef Reisinger <reisinge@cpan.org>
=head1 COPYRIGHT AND LICENSE
This software is copyright (c) 2017 by Jozef Reisinger.
This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.
=cut
__DATA__
boot_time last | grep boot | head -1 | perl -lane 'print join " ", @F[4..7]'
big_palindromes perl -lne 'print if $_ eq reverse and length >= 5' /usr/share/dict/words
free_mem free -m | grep -E '^Mem:' | perl -lane '($total,$free,$buffers,$cached) = ( /(\d+)/g )[0,2,4,5]; printf "%.0f%%\n", ($free+$buffers+$cached)/$total*100'
cpu_info lscpu | perl -0777 -ne '$ncpu=$1 if /^CPU\(s\):\s*(\d+)/m; $mhz=$1 if /^CPU MHz:\s*([\d\.]+)/m; END { printf "%s x %.0fMHz\n", $ncpu, $mhz }'
mem_info cat /proc/meminfo | perl -ne 'printf "%.0fMB\n", $1/1000 if /^MemTotal:\s*(\d+)/'
view all matches for this distributionview release on metacpan - search on metacpan
( run in 0.751 second using v1.00-cache-2.02-grep-82fe00e-cpan-dad7e4baca0 )