App-MultiSsh

 view release on metacpan or  search on metacpan

lib/App/MultiSsh.pm  view on Meta::CPAN

            }
        }
        else {
            print "$host -\n" if $option->{verbose};
            system $cmd;
        }
    }

    # reap any outstanding children
    wait;
}

sub _read_label_line {
    my ( $in_fh, $out_fh, $host ) = @_;
    state %hosts;
    my @colours = (
        qw/
          red     on_red     bright_red
          green   on_green   bright_green
          blue    on_blue    bright_blue
          magenta on_magenta bright_magenta
          cyan    on_cyan
          yellow  on_yellow
          /
    );
    return if !$in_fh;

    my $line = <$in_fh>;

    if ( !defined $line && $! != EAGAIN ) {
        close $in_fh;
        return;
    }

    if ( defined $line ) {
        $hosts{$host} ||= $colours[ rand @colours ];
        require Term::ANSIColor;
        print {$out_fh} '[', Term::ANSIColor::colored( $host, $hosts{$host} ),
          '] ', $line;
    }

    return $in_fh;
}

sub tmux {
    my ( $option, @commands ) = @_;

    confess "No commands for tmux to run!\n" if !@commands;

    my $layout = layout(@commands);
    my $tmux   = '';
    my $final  = '';
    my $pct    = int( 100 / scalar @commands );

    for my $ssh (@commands) {
        if ( !$tmux && $option->{tmux_nested} ) {
            $tmux = ' rename-window mssh';
            $final =
              '; bash -c '
              . shell_quote(
                "echo $ssh; echo 'set-window-option synchronize-panes on|off'")
              . '\\;'
              . shell_quote($ssh);
        }
        else {
            my $cmd = !$tmux ? 'new-session' : '\\; split-window -d -p ' . $pct;

            $tmux .=
              " $cmd " . shell_quote("echo $ssh") . '\\;' . shell_quote($ssh);
        }
    }

    my $sync = $option->{tmux_sync} ? 'on' : 'off';
    $tmux .= " \\; set-window-option synchronize-panes $sync"
      if $commands[0] !~ /\s$/xms;

    return
"tmux$tmux \\; select-layout tiled \\; setw synchronize-panes $sync$final";
}

sub layout {
    my (@commands) = @_;
    my $rows       = int sqrt @commands + 1;
    my $cols       = ceil @commands / $rows;
    my $out        = [];
    if ( $cols > $rows + 1 ) {
        my $tmp = $rows;
        $rows++;
        $cols--;
    }
  ROW:
    for my $row ( 0 .. $rows - 1 ) {
        for my $col ( 0 .. $cols - 1 ) {
            last ROW if !@commands;
            $out->[$row][$col] = shift @commands;
        }
    }

    return $out;
}

sub config {
    state $config;
    return $config if $config;

    my $config_file = path( $ENV{HOME}, '.mssh' );
    if ( !-f $config_file ) {
        $config = {};

        # create a default config file
        $config_file->spew("---\ngroups:\n  eg:\n    - host1\n    - host2\n");

        return $config;
    }

    require YAML;
    $config = YAML::LoadFile($config_file);

    return $config;
}

sub get_groups {
    my ($groups) = @_;
    my $config = config();
    my @hosts;

    for my $group (@$groups) {
        if ( $config->{groups} && $config->{groups}{$group} ) {
            push @hosts,
              ref $config->{groups}{$group}
              ? @{ $config->{groups}{$group} }
              : $config->{groups}{$group};
        }
        else {
            warn "No host group '$group' defined in the config!\n";
        }
    }



( run in 0.409 second using v1.01-cache-2.11-cpan-39bf76dae61 )