2009-12-19 17:30:00 +00:00
|
|
|
use warnings;
|
|
|
|
use strict;
|
2018-11-24 23:37:51 +00:00
|
|
|
package App::ClusterSSH;
|
|
|
|
|
|
|
|
# ABSTRACT: Cluster administration tool
|
|
|
|
# ABSTRACT: Cluster administration tool
|
|
|
|
|
2020-06-20 10:30:48 +01:00
|
|
|
use version; our $VERSION = version->new('4.16');
|
2010-06-03 19:03:58 +01:00
|
|
|
|
2018-11-24 23:37:51 +00:00
|
|
|
=head1 SYNOPSIS
|
|
|
|
|
|
|
|
There is nothing in this module for public consumption. See documentation
|
|
|
|
for F<cssh>, F<crsh>, F<ctel>, F<ccon>, or F<cscp> instead.
|
|
|
|
|
|
|
|
=head1 DESCRIPTION
|
|
|
|
|
|
|
|
This is the core for App::ClusterSSH. You should probably look at L<cssh>
|
|
|
|
instead.
|
|
|
|
|
|
|
|
=head1 SUBROUTINES/METHODS
|
|
|
|
|
|
|
|
These methods are listed here to tidy up Pod::Coverage test reports but
|
|
|
|
will most likely be moved into other modules. There are some notes within
|
|
|
|
the code until this time.
|
|
|
|
|
|
|
|
=over 2
|
|
|
|
|
|
|
|
=cut
|
|
|
|
|
2015-03-19 17:58:01 +01:00
|
|
|
use Carp qw/cluck :DEFAULT/;
|
2010-06-03 19:03:58 +01:00
|
|
|
|
|
|
|
use base qw/ App::ClusterSSH::Base /;
|
2010-06-18 23:17:42 +01:00
|
|
|
use App::ClusterSSH::Host;
|
2011-07-21 08:23:49 +01:00
|
|
|
use App::ClusterSSH::Config;
|
2011-08-31 21:01:12 +01:00
|
|
|
use App::ClusterSSH::Helper;
|
2011-11-21 22:03:54 +00:00
|
|
|
use App::ClusterSSH::Cluster;
|
2014-05-17 17:32:03 +01:00
|
|
|
use App::ClusterSSH::Getopt;
|
2017-12-23 11:42:40 +00:00
|
|
|
use App::ClusterSSH::Window;
|
2011-08-31 21:01:12 +01:00
|
|
|
|
|
|
|
use FindBin qw($Script);
|
2010-06-03 19:03:58 +01:00
|
|
|
|
|
|
|
use POSIX ":sys_wait_h";
|
2010-06-18 22:10:33 +01:00
|
|
|
use POSIX qw/:sys_wait_h strftime mkfifo/;
|
|
|
|
use File::Temp qw/:POSIX/;
|
|
|
|
use Fcntl;
|
|
|
|
use File::Basename;
|
|
|
|
use Net::hostent;
|
|
|
|
use Sys::Hostname;
|
|
|
|
use English;
|
2010-09-10 16:00:01 +01:00
|
|
|
use Socket;
|
2015-11-09 22:46:02 +00:00
|
|
|
use File::Path qw(make_path);
|
2010-06-03 19:03:58 +01:00
|
|
|
|
|
|
|
# Notes on general order of processing
|
|
|
|
#
|
|
|
|
# parse cmd line options for extra config files
|
|
|
|
# load system configuration files
|
|
|
|
# load cfg files from options
|
|
|
|
# overlay rest of cmd line args onto options
|
|
|
|
# record all clusters
|
2014-02-17 15:39:20 -08:00
|
|
|
# parse given tags/hostnames and resolve to connections
|
2010-06-03 19:03:58 +01:00
|
|
|
# open terminals
|
|
|
|
# optionally open console if required
|
|
|
|
|
|
|
|
sub new {
|
|
|
|
my ( $class, %args ) = @_;
|
|
|
|
|
|
|
|
my $self = $class->SUPER::new(%args);
|
|
|
|
|
2014-12-12 17:15:43 +00:00
|
|
|
$self->{cluster} = App::ClusterSSH::Cluster->new( parent => $self, );
|
2014-06-28 11:40:00 +01:00
|
|
|
$self->{options} = App::ClusterSSH::Getopt->new( parent => $self, );
|
2014-12-12 10:25:03 +00:00
|
|
|
$self->{config} = App::ClusterSSH::Config->new( parent => $self, );
|
2014-12-12 17:15:43 +00:00
|
|
|
$self->{helper} = App::ClusterSSH::Helper->new( parent => $self, );
|
2017-12-23 11:42:40 +00:00
|
|
|
$self->{window} = App::ClusterSSH::Window->new( parent => $self, );
|
2011-07-21 08:23:49 +01:00
|
|
|
|
2016-04-08 21:24:22 +01:00
|
|
|
$self->set_config( $self->config );
|
2016-04-08 21:17:52 +01:00
|
|
|
|
2010-06-03 19:03:58 +01:00
|
|
|
# catch and reap any zombies
|
2014-06-21 08:30:23 +01:00
|
|
|
$SIG{CHLD} = sub {
|
|
|
|
my $kid;
|
|
|
|
do {
|
|
|
|
$kid = waitpid( -1, WNOHANG );
|
|
|
|
$self->debug( 2, "REAPER currently returns: $kid" );
|
|
|
|
} until ( $kid == -1 || $kid == 0 );
|
|
|
|
};
|
2010-06-03 19:03:58 +01:00
|
|
|
|
|
|
|
return $self;
|
|
|
|
}
|
|
|
|
|
2011-07-21 08:23:49 +01:00
|
|
|
sub config {
|
|
|
|
my ($self) = @_;
|
|
|
|
return $self->{config};
|
|
|
|
}
|
|
|
|
|
2011-11-21 22:03:54 +00:00
|
|
|
sub cluster {
|
|
|
|
my ($self) = @_;
|
|
|
|
return $self->{cluster};
|
|
|
|
}
|
|
|
|
|
2011-08-31 21:01:12 +01:00
|
|
|
sub helper {
|
|
|
|
my ($self) = @_;
|
|
|
|
return $self->{helper};
|
|
|
|
}
|
|
|
|
|
2014-05-17 17:32:03 +01:00
|
|
|
sub options {
|
|
|
|
my ($self) = @_;
|
|
|
|
return $self->{options};
|
|
|
|
}
|
|
|
|
|
|
|
|
sub getopts {
|
|
|
|
my ($self) = @_;
|
2014-06-21 08:30:23 +01:00
|
|
|
return $self->options->getopts;
|
2014-05-17 17:32:03 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
sub add_option {
|
2014-06-28 11:40:00 +01:00
|
|
|
my ( $self, %args ) = @_;
|
2014-05-17 17:32:03 +01:00
|
|
|
return $self->{options}->add_option(%args);
|
2010-06-03 19:03:58 +01:00
|
|
|
}
|
2009-12-19 17:30:00 +00:00
|
|
|
|
2017-12-23 11:42:40 +00:00
|
|
|
sub window {
|
|
|
|
my ($self) = @_;
|
|
|
|
return $self->{window};
|
|
|
|
}
|
|
|
|
|
2010-06-18 22:10:33 +01:00
|
|
|
# Set up UTF-8 on STDOUT
|
|
|
|
binmode STDOUT, ":utf8";
|
|
|
|
|
|
|
|
#use bytes;
|
|
|
|
|
|
|
|
### all sub-routines ###
|
|
|
|
|
|
|
|
# catch_all exit routine that should always be used
|
|
|
|
sub exit_prog() {
|
2014-06-21 08:30:23 +01:00
|
|
|
my ($self) = @_;
|
|
|
|
$self->debug( 3, "Exiting via normal routine" );
|
2010-06-18 22:10:33 +01:00
|
|
|
|
2017-12-22 11:36:09 +00:00
|
|
|
if ( $self->config->{external_command_pipe}
|
|
|
|
&& -e $self->config->{external_command_pipe} )
|
|
|
|
{
|
|
|
|
close( $self->{external_command_pipe_fh} )
|
|
|
|
or warn(
|
|
|
|
"Could not close pipe "
|
|
|
|
. $self->config->{external_command_pipe} . ": ",
|
|
|
|
$!
|
|
|
|
);
|
|
|
|
$self->debug( 2, "Removing external command pipe" );
|
|
|
|
unlink( $self->config->{external_command_pipe} )
|
|
|
|
|| warn "Could not unlink "
|
|
|
|
. $self->config->{external_command_pipe}
|
|
|
|
. ": ", $!;
|
|
|
|
}
|
|
|
|
|
2017-12-23 11:42:40 +00:00
|
|
|
$self->window->terminate_all_hosts;
|
|
|
|
|
2010-06-18 22:10:33 +01:00
|
|
|
exit 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
sub evaluate_commands {
|
2011-11-17 22:53:06 +00:00
|
|
|
my ($self) = @_;
|
2010-06-18 22:10:33 +01:00
|
|
|
my ( $return, $user, $port, $host );
|
|
|
|
|
|
|
|
# break apart the given host string to check for user or port configs
|
2014-06-28 11:40:00 +01:00
|
|
|
my $evaluate = $self->options->evaluate;
|
|
|
|
print "{evaluate}=", $evaluate, "\n";
|
2014-06-28 11:39:28 +01:00
|
|
|
$user = $1 if ( ${evaluate} =~ s/^(.*)@// );
|
|
|
|
$port = $1 if ( ${evaluate} =~ s/:(\w+)$// );
|
|
|
|
$host = ${evaluate};
|
2010-06-18 22:10:33 +01:00
|
|
|
|
|
|
|
$user = $user ? "-l $user" : "";
|
2011-11-17 22:53:06 +00:00
|
|
|
if ( $self->config->{comms} eq "telnet" ) {
|
|
|
|
$port = $port ? " $port" : "";
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
$port = $port ? "-p $port" : "";
|
|
|
|
}
|
|
|
|
|
|
|
|
print STDERR "Testing terminal - running command:\n";
|
|
|
|
|
|
|
|
my $command = "$^X -e 'print \"Base terminal test\n\"; sleep 2'";
|
|
|
|
|
|
|
|
my $terminal_command = join( ' ',
|
|
|
|
$self->config->{terminal},
|
|
|
|
$self->config->{terminal_allow_send_events}, "-e " );
|
|
|
|
|
|
|
|
my $run_command = "$terminal_command $command";
|
|
|
|
|
|
|
|
print STDERR $run_command, $/;
|
|
|
|
|
|
|
|
system($run_command);
|
|
|
|
print STDERR "\nTesting comms - running command:\n";
|
|
|
|
|
|
|
|
my $comms_command = join( ' ',
|
|
|
|
$self->config->{ $self->config->{comms} },
|
|
|
|
$self->config->{ $self->config->{comms} . "_args" } );
|
|
|
|
|
|
|
|
if ( $self->config->{comms} eq "telnet" ) {
|
|
|
|
$comms_command .= " $host $port";
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
$comms_command
|
|
|
|
.= " $user $port $host hostname ; echo Got hostname via ssh; sleep 2";
|
|
|
|
}
|
|
|
|
|
|
|
|
print STDERR $comms_command, $/;
|
|
|
|
|
|
|
|
system($comms_command);
|
|
|
|
|
|
|
|
$run_command = "$terminal_command '$comms_command'";
|
|
|
|
print STDERR $run_command, $/;
|
|
|
|
|
|
|
|
system($run_command);
|
2010-06-18 22:10:33 +01:00
|
|
|
|
2014-06-21 08:30:23 +01:00
|
|
|
$self->exit_prog;
|
2010-06-18 22:10:33 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
sub resolve_names(@) {
|
2011-11-18 22:31:12 +00:00
|
|
|
my ( $self, @servers ) = @_;
|
2014-06-21 08:30:23 +01:00
|
|
|
$self->debug( 2, 'Resolving cluster names: started' );
|
2010-06-18 22:10:33 +01:00
|
|
|
|
|
|
|
foreach (@servers) {
|
|
|
|
my $dirty = $_;
|
|
|
|
my $username = q{};
|
2014-06-21 08:30:23 +01:00
|
|
|
$self->debug( 3, 'Checking tag ', $_ );
|
2010-06-18 22:10:33 +01:00
|
|
|
|
|
|
|
if ( $dirty =~ s/^(.*)@// ) {
|
|
|
|
$username = $1;
|
|
|
|
}
|
2013-03-19 18:07:39 +00:00
|
|
|
|
|
|
|
my @tag_list = $self->cluster->get_tag($dirty);
|
|
|
|
|
2011-11-18 22:31:12 +00:00
|
|
|
if ( $self->config->{use_all_a_records}
|
2010-09-10 16:00:01 +01:00
|
|
|
&& $dirty !~ m/^(\d{1,3}\.?){4}$/
|
2013-03-25 13:13:03 +00:00
|
|
|
&& !@tag_list )
|
2010-09-10 16:00:01 +01:00
|
|
|
{
|
|
|
|
my $hostobj = gethostbyname($dirty);
|
|
|
|
if ( defined($hostobj) ) {
|
|
|
|
my @alladdrs = map { inet_ntoa($_) } @{ $hostobj->addr_list };
|
2014-05-13 15:22:18 +01:00
|
|
|
$self->cluster->register_tag( $dirty, @alladdrs );
|
2010-09-10 16:00:01 +01:00
|
|
|
if ( $#alladdrs > 0 ) {
|
2014-06-21 08:30:23 +01:00
|
|
|
$self->debug( 3, 'Expanded to ',
|
2014-06-28 11:40:00 +01:00
|
|
|
join( ' ', $self->cluster->get_tag($dirty) ) );
|
2014-05-13 15:22:18 +01:00
|
|
|
@tag_list = $self->cluster->get_tag($dirty);
|
2010-09-10 16:00:01 +01:00
|
|
|
}
|
|
|
|
else {
|
2014-05-13 15:22:18 +01:00
|
|
|
# don't expand if there is only one record found
|
2014-06-21 08:30:23 +01:00
|
|
|
$self->debug( 3, 'Only one A record' );
|
2010-09-10 16:00:01 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2013-03-25 13:13:03 +00:00
|
|
|
if (@tag_list) {
|
2014-06-21 08:30:23 +01:00
|
|
|
$self->debug( 3, '... it is a cluster' );
|
2013-03-25 13:13:03 +00:00
|
|
|
foreach my $node (@tag_list) {
|
2010-06-18 22:10:33 +01:00
|
|
|
if ($username) {
|
|
|
|
$node =~ s/^(.*)@//;
|
|
|
|
$node = $username . '@' . $node;
|
|
|
|
}
|
|
|
|
push( @servers, $node );
|
|
|
|
}
|
|
|
|
$_ = q{};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-03-25 13:13:03 +00:00
|
|
|
# now run everything through the external command, if one is defined
|
|
|
|
if ( $self->config->{external_cluster_command} ) {
|
|
|
|
$self->debug( 4, 'External cluster command defined' );
|
|
|
|
|
|
|
|
# use a second array here in case of failure so previously worked
|
|
|
|
# out entries are not lost
|
|
|
|
my @new_servers;
|
|
|
|
eval {
|
2014-09-19 23:01:41 +01:00
|
|
|
@new_servers = $self->cluster->get_external_clusters(@servers);
|
2013-03-25 13:13:03 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
if ($@) {
|
2013-04-15 21:34:05 +01:00
|
|
|
warn $@, $/;
|
2013-03-25 13:13:03 +00:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
@servers = @new_servers;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-06-18 22:10:33 +01:00
|
|
|
# now clean the array up
|
|
|
|
@servers = grep { $_ !~ m/^$/ } @servers;
|
|
|
|
|
2013-03-25 13:13:03 +00:00
|
|
|
if ( $self->config->{unique_servers} ) {
|
2014-06-21 08:30:23 +01:00
|
|
|
$self->debug( 3, 'removing duplicate server names' );
|
2017-12-27 16:35:35 +00:00
|
|
|
@servers = $self->remove_repeated_servers(@servers);
|
2013-02-27 10:26:05 +00:00
|
|
|
}
|
|
|
|
|
2014-06-21 08:30:23 +01:00
|
|
|
$self->debug( 3, 'leaving with ', $_ ) foreach (@servers);
|
|
|
|
$self->debug( 2, 'Resolving cluster names: completed' );
|
2010-06-18 22:10:33 +01:00
|
|
|
return (@servers);
|
|
|
|
}
|
|
|
|
|
2013-02-27 10:26:05 +00:00
|
|
|
sub remove_repeated_servers {
|
2017-12-27 16:35:35 +00:00
|
|
|
my $self = shift;
|
|
|
|
my %all = ();
|
2013-03-25 13:13:03 +00:00
|
|
|
@all{@_} = 1;
|
|
|
|
return ( keys %all );
|
2013-02-27 10:26:05 +00:00
|
|
|
}
|
|
|
|
|
2010-06-18 22:10:33 +01:00
|
|
|
sub run {
|
2010-06-18 23:17:42 +01:00
|
|
|
my ($self) = @_;
|
2010-06-18 22:10:33 +01:00
|
|
|
|
2014-05-17 17:32:03 +01:00
|
|
|
$self->getopts;
|
2010-06-18 22:10:33 +01:00
|
|
|
|
|
|
|
### main ###
|
|
|
|
|
2017-12-23 11:42:40 +00:00
|
|
|
$self->window->initialise;
|
2010-06-18 22:10:33 +01:00
|
|
|
|
2018-11-24 23:37:51 +00:00
|
|
|
$self->debug( 2, "VERSION: ", $__PACKAGE__::VERSION );
|
2011-11-24 21:48:35 +00:00
|
|
|
|
2014-09-19 23:01:41 +01:00
|
|
|
# only use ssh_args from options if config file ssh_args not set AND
|
|
|
|
# options is not the default value otherwise the default options
|
|
|
|
# value is used instead of the config file
|
2015-09-21 22:19:22 +01:00
|
|
|
if ( $self->config->{comms} eq 'ssh' ) {
|
2017-12-23 22:45:28 +00:00
|
|
|
if ( defined $self->config->{ssh_args} ) {
|
2015-09-21 22:19:22 +01:00
|
|
|
if ( $self->options->options
|
|
|
|
&& $self->options->options ne
|
|
|
|
$self->options->options_default )
|
|
|
|
{
|
|
|
|
$self->config->{ssh_args} = $self->options->options;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
$self->config->{ssh_args} = $self->options->options
|
|
|
|
if ( $self->options->options );
|
2014-09-19 23:01:41 +01:00
|
|
|
}
|
|
|
|
}
|
2011-11-25 22:09:33 +00:00
|
|
|
|
2014-06-28 11:39:28 +01:00
|
|
|
$self->config->{terminal_args} = $self->options->term_args
|
|
|
|
if ( $self->options->term_args );
|
2011-11-25 22:09:33 +00:00
|
|
|
|
|
|
|
if ( $self->config->{terminal_args} =~ /-class (\w+)/ ) {
|
|
|
|
$self->config->{terminal_allow_send_events}
|
|
|
|
= "-xrm '$1.VT100.allowSendEvents:true'";
|
|
|
|
}
|
|
|
|
|
2014-06-28 11:40:00 +01:00
|
|
|
$self->config->dump() if ( $self->options->dump_config );
|
2010-06-18 22:10:33 +01:00
|
|
|
|
2014-06-27 18:17:22 +01:00
|
|
|
$self->evaluate_commands() if ( $self->options->evaluate );
|
2010-06-18 22:10:33 +01:00
|
|
|
|
2017-12-23 11:42:40 +00:00
|
|
|
$self->window->get_font_size();
|
2011-11-18 22:19:00 +00:00
|
|
|
|
2017-12-23 11:42:40 +00:00
|
|
|
$self->window->load_keyboard_map();
|
2010-06-18 22:10:33 +01:00
|
|
|
|
2011-11-21 22:03:54 +00:00
|
|
|
# read in normal cluster files
|
2014-06-28 11:39:28 +01:00
|
|
|
$self->config->{extra_cluster_file} .= ',' . $self->options->cluster_file
|
|
|
|
if ( $self->options->cluster_file );
|
|
|
|
$self->config->{extra_tag_file} .= ',' . $self->options->tag_file
|
|
|
|
if ( $self->options->tag_file );
|
2010-06-18 22:10:33 +01:00
|
|
|
|
2013-03-25 13:13:03 +00:00
|
|
|
$self->cluster->get_cluster_entries( split /,/,
|
|
|
|
$self->config->{extra_cluster_file} || '' );
|
|
|
|
$self->cluster->get_tag_entries( split /,/,
|
|
|
|
$self->config->{extra_tag_file} || '' );
|
2011-11-21 22:03:54 +00:00
|
|
|
|
2017-12-23 11:42:40 +00:00
|
|
|
my @servers;
|
|
|
|
|
2015-11-15 22:53:04 +00:00
|
|
|
if ( defined $self->options->list ) {
|
|
|
|
my $eol = $self->options->quiet ? ' ' : $/;
|
|
|
|
my $tab = $self->options->quiet ? '' : "\t";
|
|
|
|
if ( !$self->options->list ) {
|
|
|
|
print( 'Available cluster tags:', $/ )
|
2015-11-15 22:03:54 +00:00
|
|
|
unless ( $self->options->quiet );
|
2015-11-15 22:53:04 +00:00
|
|
|
print $tab, $_, $eol
|
|
|
|
foreach ( sort( $self->cluster->list_tags ) );
|
|
|
|
|
|
|
|
my @external_clusters = $self->cluster->list_external_clusters;
|
|
|
|
if (@external_clusters) {
|
|
|
|
print( 'Available external command tags:', $/ )
|
|
|
|
unless ( $self->options->quiet );
|
|
|
|
print $tab, $_, $eol foreach ( sort(@external_clusters) );
|
|
|
|
print $/;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
print 'Tag resolved to hosts: ', $/
|
|
|
|
unless ( $self->options->quiet );
|
|
|
|
@servers = $self->resolve_names( $self->options->list );
|
|
|
|
|
|
|
|
foreach my $svr (@servers) {
|
|
|
|
print $tab, $svr, $eol;
|
|
|
|
}
|
|
|
|
print $/;
|
2014-08-10 10:36:22 +01:00
|
|
|
}
|
2014-07-05 20:25:14 +01:00
|
|
|
|
2013-03-25 13:13:03 +00:00
|
|
|
$self->debug(
|
|
|
|
4,
|
|
|
|
"Full clusters dump: ",
|
|
|
|
$self->_dump_args_hash( $self->cluster->dump_tags )
|
|
|
|
);
|
2014-06-21 08:30:23 +01:00
|
|
|
$self->exit_prog();
|
2011-11-21 22:03:54 +00:00
|
|
|
}
|
2010-09-09 21:22:53 +01:00
|
|
|
|
2010-06-18 22:10:33 +01:00
|
|
|
if (@ARGV) {
|
2011-11-18 22:31:12 +00:00
|
|
|
@servers = $self->resolve_names(@ARGV);
|
2010-06-18 22:10:33 +01:00
|
|
|
}
|
|
|
|
else {
|
2014-01-04 15:07:34 +00:00
|
|
|
|
|
|
|
#if ( my @default = $self->cluster->get_tag('default') ) {
|
2011-11-21 22:03:54 +00:00
|
|
|
if ( $self->cluster->get_tag('default') ) {
|
2011-11-18 22:31:12 +00:00
|
|
|
@servers
|
2014-01-04 15:07:34 +00:00
|
|
|
|
|
|
|
# = $self->resolve_names( @default );
|
2011-11-21 22:03:54 +00:00
|
|
|
= $self->resolve_names( $self->cluster->get_tag('default') );
|
2010-06-18 22:10:33 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-12-23 11:42:40 +00:00
|
|
|
$self->window->create_windows();
|
|
|
|
$self->window->create_menubar();
|
2010-06-18 22:10:33 +01:00
|
|
|
|
2017-12-23 11:42:40 +00:00
|
|
|
$self->window->change_main_window_title();
|
2010-06-18 22:10:33 +01:00
|
|
|
|
2014-06-21 08:30:23 +01:00
|
|
|
$self->debug( 2, "Capture map events" );
|
2017-12-23 11:42:40 +00:00
|
|
|
$self->window->capture_map_events();
|
2010-06-18 22:10:33 +01:00
|
|
|
|
2015-11-15 22:03:54 +00:00
|
|
|
$self->debug( 0, 'Opening to: ', join( ' ', @servers ) )
|
|
|
|
if ( @servers && !$self->options->quiet );
|
2017-12-23 11:42:40 +00:00
|
|
|
$self->window->open_client_windows(@servers);
|
2010-06-18 22:10:33 +01:00
|
|
|
|
|
|
|
# Check here if we are tiling windows. Here instead of in func so
|
|
|
|
# can be tiled from console window if wanted
|
2011-07-28 10:23:49 +01:00
|
|
|
if ( $self->config->{window_tiling} eq "yes" ) {
|
2017-12-23 11:42:40 +00:00
|
|
|
$self->window->retile_hosts();
|
2010-06-18 22:10:33 +01:00
|
|
|
}
|
|
|
|
else {
|
2017-12-23 11:42:40 +00:00
|
|
|
$self->window->show_console();
|
2010-06-18 22:10:33 +01:00
|
|
|
}
|
|
|
|
|
2017-12-23 11:42:40 +00:00
|
|
|
$self->window->build_hosts_menu();
|
2010-06-18 22:10:33 +01:00
|
|
|
|
2014-06-21 08:30:23 +01:00
|
|
|
$self->debug( 2, "Sleeping for a mo" );
|
2010-06-18 22:10:33 +01:00
|
|
|
select( undef, undef, undef, 0.5 );
|
|
|
|
|
2017-12-23 11:42:40 +00:00
|
|
|
$self->window->console_focus;
|
2010-06-18 22:10:33 +01:00
|
|
|
|
2017-12-22 11:36:09 +00:00
|
|
|
# set up external command pipe
|
|
|
|
if ( $self->config->{external_command_pipe} ) {
|
|
|
|
|
|
|
|
if ( -e $self->config->{external_command_pipe} ) {
|
|
|
|
$self->debug( 1, "Removing pre-existing external command pipe" );
|
|
|
|
unlink( $self->config->{external_command_pipe} )
|
|
|
|
or die(
|
|
|
|
"Could not remove "
|
|
|
|
. $self->config->{external_command_pipe}
|
|
|
|
. " prior to creation: "
|
|
|
|
. $!,
|
|
|
|
$/
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
$self->debug( 2, "Creating external command pipe" );
|
|
|
|
|
|
|
|
mkfifo(
|
|
|
|
$self->config->{external_command_pipe},
|
|
|
|
oct( $self->config->{external_command_mode} )
|
|
|
|
)
|
|
|
|
or die(
|
|
|
|
"Could not create "
|
|
|
|
. $self->config->{external_command_pipe} . ": ",
|
|
|
|
$!
|
|
|
|
);
|
|
|
|
|
|
|
|
sysopen(
|
|
|
|
$self->{external_command_pipe_fh},
|
|
|
|
$self->config->{external_command_pipe},
|
|
|
|
O_NONBLOCK | O_RDONLY
|
|
|
|
)
|
|
|
|
or die(
|
|
|
|
"Could not open " . $self->config->{external_command_pipe} . ": ",
|
|
|
|
$!
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2014-06-21 08:30:23 +01:00
|
|
|
$self->debug( 2, "Setting up repeat" );
|
2017-12-23 11:42:40 +00:00
|
|
|
$self->window->setup_repeat();
|
2010-06-18 22:10:33 +01:00
|
|
|
|
|
|
|
# Start event loop
|
2014-06-21 08:30:23 +01:00
|
|
|
$self->debug( 2, "Starting MainLoop" );
|
2017-12-23 11:42:40 +00:00
|
|
|
$self->window->mainloop();
|
2010-06-18 22:10:33 +01:00
|
|
|
|
|
|
|
# make sure we leave program in an expected way
|
2014-06-21 08:30:23 +01:00
|
|
|
$self->exit_prog();
|
2010-06-18 22:10:33 +01:00
|
|
|
}
|
|
|
|
|
2009-12-19 17:30:00 +00:00
|
|
|
1;
|
|
|
|
|
|
|
|
|
2010-06-18 23:25:49 +01:00
|
|
|
=item REAPER
|
2009-12-19 17:30:00 +00:00
|
|
|
|
2010-06-18 23:25:49 +01:00
|
|
|
=item add_host_by_name
|
2009-12-19 17:30:00 +00:00
|
|
|
|
2014-06-29 12:49:37 +01:00
|
|
|
=item add_option
|
|
|
|
|
2010-06-18 23:25:49 +01:00
|
|
|
=item build_hosts_menu
|
2009-12-19 17:30:00 +00:00
|
|
|
|
2010-06-18 23:25:49 +01:00
|
|
|
=item capture_map_events
|
|
|
|
|
|
|
|
=item capture_terminal
|
|
|
|
|
|
|
|
=item change_main_window_title
|
|
|
|
|
2014-06-29 12:49:37 +01:00
|
|
|
=item close_inactive_sessions
|
2010-06-18 23:25:49 +01:00
|
|
|
|
2014-06-29 12:49:37 +01:00
|
|
|
=item config
|
2011-07-21 08:23:49 +01:00
|
|
|
|
2014-06-29 12:49:37 +01:00
|
|
|
=item helper
|
2011-08-31 21:01:12 +01:00
|
|
|
|
2011-11-24 21:48:35 +00:00
|
|
|
=item cluster
|
|
|
|
|
2014-06-29 12:49:37 +01:00
|
|
|
=item create_menubar
|
|
|
|
|
|
|
|
=item create_windows
|
|
|
|
|
|
|
|
=item dump_config
|
2010-06-18 23:25:49 +01:00
|
|
|
|
2014-06-29 12:49:37 +01:00
|
|
|
=item getopts
|
2010-06-18 23:25:49 +01:00
|
|
|
|
2014-06-29 12:49:37 +01:00
|
|
|
=item list_tags
|
2010-06-18 23:25:49 +01:00
|
|
|
|
2014-06-29 12:49:37 +01:00
|
|
|
=item evaluate_commands
|
2010-09-09 21:22:53 +01:00
|
|
|
|
2014-06-29 12:49:37 +01:00
|
|
|
=item exit_prog
|
2010-06-18 23:25:49 +01:00
|
|
|
|
2014-06-29 12:49:37 +01:00
|
|
|
=item get_clusters
|
2010-06-18 23:25:49 +01:00
|
|
|
|
2014-06-29 12:49:37 +01:00
|
|
|
=item get_font_size
|
2010-06-18 23:25:49 +01:00
|
|
|
|
2014-06-29 12:49:37 +01:00
|
|
|
=item get_keycode_state
|
2010-06-18 23:25:49 +01:00
|
|
|
|
2014-06-29 12:49:37 +01:00
|
|
|
=item key_event
|
2010-06-18 23:25:49 +01:00
|
|
|
|
2014-06-29 12:49:37 +01:00
|
|
|
=item load_config_defaults
|
2010-06-18 23:25:49 +01:00
|
|
|
|
2014-06-29 12:49:37 +01:00
|
|
|
=item load_configfile
|
2010-06-18 23:25:49 +01:00
|
|
|
|
2014-06-29 12:49:37 +01:00
|
|
|
=item load_keyboard_map
|
2010-06-18 23:25:49 +01:00
|
|
|
|
2014-06-29 12:49:37 +01:00
|
|
|
=item new
|
2009-12-19 17:30:00 +00:00
|
|
|
|
2014-06-29 12:49:37 +01:00
|
|
|
=item open_client_windows
|
2009-12-19 17:30:00 +00:00
|
|
|
|
2014-06-29 12:49:37 +01:00
|
|
|
=item options
|
2010-06-18 23:25:49 +01:00
|
|
|
|
2014-06-29 12:49:37 +01:00
|
|
|
=item parse_config_file
|
2010-06-18 23:25:49 +01:00
|
|
|
|
2014-06-29 12:49:37 +01:00
|
|
|
=item pick_color
|
2010-06-18 23:25:49 +01:00
|
|
|
|
2014-06-29 12:49:37 +01:00
|
|
|
=item populate_send_menu
|
2010-06-18 23:25:49 +01:00
|
|
|
|
2014-06-29 12:49:37 +01:00
|
|
|
=item populate_send_menu_entries_from_xml
|
2010-06-18 23:25:49 +01:00
|
|
|
|
2015-09-21 22:19:22 +01:00
|
|
|
=item re_add_closed_sessions
|
|
|
|
|
2013-02-27 10:26:05 +00:00
|
|
|
=item remove_repeated_servers
|
|
|
|
|
2014-06-29 12:49:37 +01:00
|
|
|
=item resolve_names
|
2010-06-18 23:25:49 +01:00
|
|
|
|
2016-07-11 19:58:33 +02:00
|
|
|
=item slash_slash_equal
|
|
|
|
|
|
|
|
An implementation of the //= operator that works on older Perls.
|
|
|
|
slash_slash_equal($a, 0) is equivalent to $a //= 0
|
|
|
|
|
2014-06-29 12:49:37 +01:00
|
|
|
=item retile_hosts
|
2010-06-18 23:25:49 +01:00
|
|
|
|
2014-06-29 12:49:37 +01:00
|
|
|
=item run
|
2010-06-18 23:25:49 +01:00
|
|
|
|
2014-06-29 12:49:37 +01:00
|
|
|
=item send_resizemove
|
2010-06-18 23:25:49 +01:00
|
|
|
|
2014-06-29 12:49:37 +01:00
|
|
|
=item send_text
|
2010-06-18 23:25:49 +01:00
|
|
|
|
2014-06-29 12:49:37 +01:00
|
|
|
=item send_text_to_all_servers
|
2010-06-18 23:25:49 +01:00
|
|
|
|
2014-07-09 20:25:42 +01:00
|
|
|
=item set_all_active
|
|
|
|
|
|
|
|
=item set_half_inactive
|
|
|
|
|
2014-06-29 12:49:37 +01:00
|
|
|
=item setup_repeat
|
2010-06-18 23:25:49 +01:00
|
|
|
|
2014-09-19 23:18:22 +01:00
|
|
|
=item send_variable_text_to_all_servers
|
|
|
|
|
2014-06-29 12:49:37 +01:00
|
|
|
=item show_console
|
2010-06-18 23:25:49 +01:00
|
|
|
|
2014-06-29 12:49:37 +01:00
|
|
|
=item show_history
|
2010-06-18 23:25:49 +01:00
|
|
|
|
2015-11-09 22:46:02 +00:00
|
|
|
=item substitute_macros
|
|
|
|
|
2014-06-29 12:49:37 +01:00
|
|
|
=item terminate_host
|
2010-06-18 23:25:49 +01:00
|
|
|
|
2014-06-29 12:49:37 +01:00
|
|
|
=item toggle_active_state
|
2010-06-18 23:25:49 +01:00
|
|
|
|
2014-06-29 12:49:37 +01:00
|
|
|
=item update_display_text
|
2010-06-18 23:25:49 +01:00
|
|
|
|
2017-12-27 10:58:28 +00:00
|
|
|
=item window
|
|
|
|
|
2021-06-27 12:23:12 -07:00
|
|
|
Method to access associated window module
|
2017-12-27 10:58:28 +00:00
|
|
|
|
2014-06-29 12:49:37 +01:00
|
|
|
=item write_default_user_config
|
2010-06-18 23:25:49 +01:00
|
|
|
|
|
|
|
=back
|
2009-12-19 17:30:00 +00:00
|
|
|
|
|
|
|
=head1 BUGS
|
|
|
|
|
2017-08-03 22:43:39 +01:00
|
|
|
Please report any bugs or feature requests via L<https://github.com/duncs/clusterssh/issues>.
|
2009-12-19 17:30:00 +00:00
|
|
|
|
|
|
|
=head1 SUPPORT
|
|
|
|
|
|
|
|
You can find documentation for this module with the perldoc command.
|
|
|
|
|
|
|
|
perldoc App::ClusterSSH
|
|
|
|
|
|
|
|
You can also look for information at:
|
|
|
|
|
|
|
|
=over 4
|
|
|
|
|
2017-08-03 22:43:39 +01:00
|
|
|
=item * Github issue tracker
|
2009-12-19 17:30:00 +00:00
|
|
|
|
2017-08-03 22:43:39 +01:00
|
|
|
L<https://github.com/duncs/clusterssh/issues>
|
2009-12-19 17:30:00 +00:00
|
|
|
|
|
|
|
=item * AnnoCPAN: Annotated CPAN documentation
|
|
|
|
|
|
|
|
L<http://annocpan.org/dist/App-ClusterSSH>
|
|
|
|
|
|
|
|
=item * CPAN Ratings
|
|
|
|
|
|
|
|
L<http://cpanratings.perl.org/d/App-ClusterSSH>
|
|
|
|
|
|
|
|
=item * Search CPAN
|
|
|
|
|
|
|
|
L<http://search.cpan.org/dist/App-ClusterSSH/>
|
|
|
|
|
|
|
|
=back
|
|
|
|
|
|
|
|
=head1 ACKNOWLEDGEMENTS
|
|
|
|
|
2010-06-20 20:23:41 +01:00
|
|
|
Please see the THANKS file from the original distribution.
|
|
|
|
|
2009-12-19 17:30:00 +00:00
|
|
|
=cut
|