App-MrShell

 view release on metacpan or  search on metacpan

Changes  view on Meta::CPAN

     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

MANIFEST  view on Meta::CPAN

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)

MrShell.pm  view on Meta::CPAN

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

MrShell.pm  view on Meta::CPAN

    }

    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(@_) ];

MrShell.pm  view on Meta::CPAN

        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>

mrsh  view on Meta::CPAN

    }
}

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  view on Meta::CPAN


    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:

mrsh  view on Meta::CPAN


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'

mrsh  view on Meta::CPAN


=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 )