App-MrShell
view release on metacpan or search on metacpan
install it and fart around with it a little first though.
2.0000: Sat May 2 09:23:09 EDT 2009
- docs for mrsh
- docs for App::MrShell
2.0000: Sat May 2 07:36:41 EDT 2009
- hooray, I got the host routing stuff to actually work. I
proved it out on a test, but it wasn't terribly convincing.
Then I used this: mrsh -H 'corky!wisp!corky!razor!webserver'
'touch /tmp/holy\ shit' The escapes for that are tricky to
get right, but it *is* possible.
2.0000: Wed Apr 29 21:54:02 EDT 2009
- added all kinds of bells and whistles (ok, bugfixes)
- made the t/05 meaningful
- convinced MrShell to allow commands with various subst vars
- made the t/05 test *portable*, rather than using external
linux commands
2.0000: Wed Apr 29 21:33:06 EDT 2009
Makefile.PL
MrShell.pm
README
lib/App/MrShell.pod
make_par.sh
mrsh
t/01_load.t
t/05_touch_things.t
t/06_touch_things_w_mrsh.t
t/07_host_routing.t
t/07_host_routing_escapes.t
t/09_simplest_usersubst.t
t/10_routed_usersubst.t
t/critic.t
t/pod.t
META.yml Module meta-data (added by MakeMaker)
if( not defined $val ) {
delete $this->{debug};
return $this;
}
$this->{debug} = $val ? $val : 1;
return $this;
}
# }}}
# set_no_command_escapes_option {{{
sub set_no_command_escapes_option {
my $this = shift;
$this->{no_command_escapes} = shift || 0;
return $this;
}
# }}}
# groups {{{
sub groups {
my $this = shift;
return unless $this->{groups};
}
if( my $c = $this->{_conf}{options}{'logfile'} ) {
my $t = $this->{_conf}{options}{'truncate-logfile'};
my $v = ($t ? 1:0);
$v = 0 if $t =~ m/(?:no|false)/i;
$this->set_logfile_option($c, $v);
}
if( my $c = $this->{_conf}{options}{'no-command-escapes'} ) {
my $v = ($c ? 1:0);
$v = 0 if $c =~ m/(?:no|false)/i;
$this->set_no_command_escapes_option( $v );
}
return $this;
}
# }}}
# set_hosts {{{
sub set_hosts {
my $this = shift;
$this->{hosts} = [ $this->_process_hosts(@_) ];
for(my $i=0; $i<@c; $i++) {
if( $c[$i] eq '%h' ) {
splice @c, $i, 1, $hosts[0];
push @indexes_of_replacements, $i;
for my $h (reverse @hosts[1 .. $#hosts]) {
splice @c, $i+1, 0, @c[0 .. $i-1] => $h;
push @indexes_of_replacements, $i+1 + $indexes_of_replacements[-1];
unless( $this->{no_command_escapes} ) {
for my $arg (@c[$i+1 .. $#c]) {
# NOTE: This escaping is going to be an utter pain to maintain...
$arg =~ s/([`\$])/\\$1/g;
if( $arg =~ m/[\s()]/ ) {
$arg =~ s/([\\"])/\\$1/g;
$arg = "\"$arg\"";
}
lib/App/MrShell.pod view on Meta::CPAN
When provided, write a logfile of all lines received, where and when they were
executed.
=item B<set_debug_option>
Turn on various debugging messages. The optional argument specifies the debug
level. No argument, 0, and 1 are all equivalent. While levels greater than one
indicate an increased amount of debugging noise.
=item B<set_no_command_escapes_option>
When expanding hosts in host-routing mode, slashes and spaces are escaped so
they function correctly when subshelled. This disables that functionality.
=item B<read_config>
The options above can be specified from a L<config file|mrsh/CONFIG FILE>, which
is documented in the command line tool. The config file is read using
L<Config::Tiny>.
=item B<set_usage_error>
}
}
my $mrsh = App::MrShell->new->set_usage_error("pod2usage");
$mrsh->read_config($conf) if $conf;
show_groups_and_exit() if $show_groups_and_exit;
$mrsh->set_logfile_option($log, $trunc) if $log;
$mrsh->set_shell_command_option($shell) if $shell;
$mrsh->set_debug_option($debug) if defined $debug;
$mrsh->set_no_command_escapes_option if $no_esc;
$mrsh->set_hosts(@hosts) # tell Mr. Shell where to run things
->queue_command(@ARGV) # queue a command for whatever hosts are set
->run_queue; # tell POE to do what POE does
sub show_groups_and_exit {
my %groups = $mrsh->groups;
my @groups = sort keys %groups;
if( my @h = grep {s/^@//} @hosts ) { ## no critic: bah
mrsh [options] [--] command
--version -v: print the version, help, and exit
--help -h: print extended help and exit
--host -H: specify a host or group to run commands on
--conf -c: specify config file location, or skip configs
--log -l: specify a logfile location
--trunc -t: overwrite logfile, rather than append
--shell -s: change the (remote-)shell command
--noesc -N: do not escape the sub commands during host-routing mode
--groups -g: show groups and exit
--list : (nickname for --groups)
-- : not strictly an option, but good to put before commands
=head1 DESCRIPTION
The B<-H> has some special magic concerning L</[groups]>. If a group is
specified before any other options or options arguments arguments (but possibly
after other groups), it will automatically be expanded to have an imaginary
B<-H> before it. Example:
The C<%h> will be replaced by the hostname(s) during execution
(see L</COMMAND ESCAPES>).
Almost any shell command will work, see C<t/05_touch_things.t> in the
distribution for using perl as a "shell" to touch files. Arguments to B<-s> are
space delimited but understand very simple quoting:
=item B<--noesc> B<-N>
During host routing mode, L<mrsh> will escape spaces and backslashes in a way
that openssh (L<http://openssh.com/>) will understand correctly. That behavior
can be completely disabled with this option.
=back
=head1 COMMAND ESCAPES
These things will be replaced before forking the commands on the remote hosts.
There aren't many of these yet, but there will likely be more in the future.
=over
=item B<%c>
The command number.
=item B<%h>
The hostname. The hostname escape supports a special host routing protocol.
Hostnames that contain the routing character will be expanded to magically
create sub-commands as needed to connect I<through> hosts while executing
commands.
When expanding a host route, all C<%h> will be replaced with the elements of
the command array up to that escape, plus the hostname, for each host in the
hosts route.
This expansion also optionally (see B<-N> above) expands spaces and slashes to
escaped values compatible with openssh (L<http://openssh.com/>).
This is perhaps more clear by example.
Let's say this is the command in question.
ssh -o 'BatchMode Yes' %h 'ls -ald /tmp/'
And let's say our hostname is C<corky!wisp>, then the command becomes:
ssh -o 'BatchMode Yes' corky ssh -o 'Batchmode\ Yes' wisp 'ls\\ -ald\\ /tmp'
=item B<default-hosts>
When no hosts are specified for a command, L<mrsh> will seek to use these hosts
and L</[groups]> instead.
=item B<shell-command>
This is the above B<-s> setting, which allows changing the shell command.
=item B<no-command-escapes>
This is the above B<-N> setting, which disables escaping of arguments during
host-routing mode.
=back
=head2 B<[groups]>
The B<[groups]> section can contain as many hostname values as ... your platform
as memory. Groups are expanded by pre-fixing with an C<@> character when passing
( run in 0.382 second using v1.01-cache-2.11-cpan-c21f80fb71c )