mirror of
https://github.com/duncs/clusterssh.git
synced 2025-04-21 00:59:07 +00:00
Add in macro_user_1 .. 4
Add in user macros that can run an external command to pass into each client terminal session. Ensure that if no user command is defined that the expected 'Alt-1' to 'Alt-4' keys are passed into the terminals instead. Include docs and examples of how they might be used.
This commit is contained in:
parent
900d0fabb6
commit
dab4fa2237
7 changed files with 222 additions and 2 deletions
1
Changes
1
Changes
|
@ -4,6 +4,7 @@ Revision history for {{$dist->name}}
|
|||
- Include README within the repository, not just created tar.gz files
|
||||
- Add 'autoquit' setting to 'File' menu (Github issue #114)
|
||||
- Correct macro_hostname to be the FQDN of the server where cssh is being run (Github issue #116)
|
||||
- Add in user defined macros
|
||||
|
||||
4.13.2_02 2019-01-14 Duncan Ferguson <duncan_ferguson@user.sf.net>
|
||||
- Fix Getopt-Long minimum version
|
||||
|
|
49
README
49
README
|
@ -83,8 +83,8 @@ OPTIONS
|
|||
Number of seconds to wait before closing finished terminal windows.
|
||||
|
||||
--autoquit, -q
|
||||
Toggle automatically quitting after the last client window has closed
|
||||
(overriding the config file).
|
||||
Toggle automatically quitting after the last client window has
|
||||
closed (overriding the config file).
|
||||
|
||||
--cluster-file '<filename>', -c '<filename>'
|
||||
Use supplied file as additional cluster file (see also "FILES").
|
||||
|
@ -223,6 +223,13 @@ KEY SHORTCUTS
|
|||
Alt-u
|
||||
Paste in the username for the connection
|
||||
|
||||
Alt-1
|
||||
Alt-2
|
||||
Alt-3
|
||||
Alt-4
|
||||
Run the matching user defined macro on the server and send the
|
||||
output to the client
|
||||
|
||||
EXAMPLES
|
||||
Open up a session to 3 servers
|
||||
$ cssh server1 server2 server3
|
||||
|
@ -418,14 +425,52 @@ FILES
|
|||
Default key sequence to send username to client. See "KEY
|
||||
SHORTCUTS" for more information.
|
||||
|
||||
key_user_1 = Alt-1
|
||||
key_user_2 = Alt-2
|
||||
key_user_3 = Alt-3
|
||||
key_user_4 = Alt-4
|
||||
Default key sequence to send user defined macros to client. If
|
||||
the matching macro_user_1 macro is undefined, the sequence is
|
||||
passed straight to the terminal. See "KEY SHORTCUTS" for more
|
||||
information.
|
||||
|
||||
macro_servername = %s
|
||||
macro_hostname = %h
|
||||
macro_username = %u
|
||||
macro_newline = %n
|
||||
macro_version = %v
|
||||
macro_user_1 = %1
|
||||
macro_user_2 = %2
|
||||
macro_user_3 = %3
|
||||
macro_user_4 = %4
|
||||
Change the replacement macro used when either using a 'Send'
|
||||
menu item, or when pasting text into the main console.
|
||||
|
||||
macro_user_1_command =
|
||||
macro_user_2_command =
|
||||
macro_user_3_command =
|
||||
macro_user_4_command =
|
||||
User defined macros - the macro is run through the shell on the
|
||||
server and the output is sent to the client. For example,
|
||||
|
||||
"macro_user_1_command=echo echo macro_user_1"
|
||||
|
||||
would send the text C<echo macro_user_1> into the terminal session.
|
||||
|
||||
"macro_user_1_command=env | grep CSSH"
|
||||
|
||||
would send the CSSH environment variables to the client.
|
||||
|
||||
The following environment variables are set in the shell of the
|
||||
macro process
|
||||
|
||||
"CSSH_SERVERNAME"
|
||||
"CSSH_HOSTNAME"
|
||||
"CSSH_USERNAME"
|
||||
"CSSH_CONNECTION_STRING"
|
||||
"CSSH_CONNECTION_PORT"
|
||||
"CSSH_VERSION"
|
||||
|
||||
macros_enabled = yes
|
||||
Enable or disable macro replacement. Note: this affects all the
|
||||
"macro_*" variables above.
|
||||
|
|
|
@ -49,6 +49,10 @@ my %default_config = (
|
|||
key_macros_enable => "Alt-p",
|
||||
key_paste => "Control-v",
|
||||
key_username => "Alt-u",
|
||||
key_user_1 => "Alt-1",
|
||||
key_user_2 => "Alt-2",
|
||||
key_user_3 => "Alt-3",
|
||||
key_user_4 => "Alt-4",
|
||||
mouse_paste => "Button-2",
|
||||
auto_quit => "yes",
|
||||
auto_close => 5,
|
||||
|
@ -103,6 +107,15 @@ my %default_config = (
|
|||
macro_username => '%u',
|
||||
macro_newline => '%n',
|
||||
macro_version => '%v',
|
||||
macro_user_1 => '%1',
|
||||
macro_user_2 => '%2',
|
||||
macro_user_3 => '%3',
|
||||
macro_user_4 => '%4',
|
||||
|
||||
macro_user_1_command => '',
|
||||
macro_user_2_command => '',
|
||||
macro_user_3_command => '',
|
||||
macro_user_4_command => '',
|
||||
|
||||
max_addhost_menu_cluster_items => 6,
|
||||
menu_send_autotearoff => 0,
|
||||
|
@ -279,6 +292,15 @@ sub parse_config_file {
|
|||
if ( $read_config{terminal_font} );
|
||||
|
||||
$self->validate_args(%read_config);
|
||||
|
||||
# Look at the user macros and if not set remove the hotkey for them
|
||||
for my $i (qw/ 1 2 3 4 /) {
|
||||
if ( ! $self->{"macro_user_${i}_command"} ) {
|
||||
delete $self->{"key_user_${i}"};
|
||||
}
|
||||
}
|
||||
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub load_configs {
|
||||
|
|
|
@ -559,6 +559,12 @@ would replace the <Alt-n> with the client's name in each window.}
|
|||
output $self->loc(q{Retile all the client windows.});
|
||||
output '=item ', $self->parent->config->{key_username};
|
||||
output $self->loc(q{Paste in the username for the connection});
|
||||
output '=item ', $self->parent->config->{key_user_1} || 'Alt-1';
|
||||
output '=item ', $self->parent->config->{key_user_2} || 'Alt-2';
|
||||
output '=item ', $self->parent->config->{key_user_3} || 'Alt-3';
|
||||
output '=item ', $self->parent->config->{key_user_4} || 'Alt-4';
|
||||
output $self->loc(q{Run the matching user defined macro on the server and send the output to the client});
|
||||
|
||||
output '=back';
|
||||
|
||||
output '=head1 ' . $self->loc('EXAMPLES');
|
||||
|
@ -768,15 +774,61 @@ If the external command is given a C<-L> option it should output a list of tags
|
|||
'L<KEY SHORTCUTS>'
|
||||
);
|
||||
|
||||
output '=item key_user_1 = Alt-1';
|
||||
output '=item key_user_2 = Alt-2';
|
||||
output '=item key_user_3 = Alt-3';
|
||||
output '=item key_user_4 = Alt-4';
|
||||
output $self->loc(
|
||||
q{Default key sequence to send user defined macros to client. If the matching [_2] macro is undefined, the sequence is passed straight to the terminal. See [_1] for more information.},
|
||||
'L<KEY SHORTCUTS>', 'L<macro_user_1>'
|
||||
);
|
||||
|
||||
output '=item macro_servername = %s';
|
||||
output '=item macro_hostname = %h';
|
||||
output '=item macro_username = %u';
|
||||
output '=item macro_newline = %n';
|
||||
output '=item macro_version = %v';
|
||||
output '=item macro_user_1 = %1';
|
||||
output '=item macro_user_2 = %2';
|
||||
output '=item macro_user_3 = %3';
|
||||
output '=item macro_user_4 = %4';
|
||||
output $self->loc(
|
||||
q{Change the replacement macro used when either using a 'Send' menu item, or when pasting text into the main console.}
|
||||
);
|
||||
|
||||
output '=item macro_user_1_command =';
|
||||
output '=item macro_user_2_command =';
|
||||
output '=item macro_user_3_command =';
|
||||
output '=item macro_user_4_command =';
|
||||
|
||||
output $self->loc(
|
||||
q{User defined macros - the macro is run through the shell on the server and the output is sent to the client. For example,},
|
||||
);
|
||||
|
||||
output "C<macro_user_1_command=echo echo macro_user_1>";
|
||||
output $self->loc(
|
||||
q{
|
||||
would send the text [_1] into the terminal session.
|
||||
},
|
||||
'C<echo macro_user_1>'
|
||||
);
|
||||
output "C<macro_user_1_command=env | grep CSSH>";
|
||||
output $self->loc(
|
||||
q{
|
||||
would send the CSSH environment variables to the client.
|
||||
},
|
||||
);
|
||||
|
||||
output $self->loc("The following environment variables are set in the shell of the macro process");
|
||||
output '=over';
|
||||
output '=item C<CSSH_SERVERNAME>';
|
||||
output '=item C<CSSH_HOSTNAME>';
|
||||
output '=item C<CSSH_USERNAME>';
|
||||
output '=item C<CSSH_CONNECTION_STRING>';
|
||||
output '=item C<CSSH_CONNECTION_PORT>';
|
||||
output '=item C<CSSH_VERSION>';
|
||||
output '=back';
|
||||
|
||||
output '=item macros_enabled = yes';
|
||||
output $self->loc(
|
||||
q{Enable or disable macro replacement. Note: this affects all the [_1] variables above.},
|
||||
|
|
|
@ -20,6 +20,8 @@ use Tk::Xlib;
|
|||
use Tk::ROText;
|
||||
require Tk::Dialog;
|
||||
require Tk::LabEntry;
|
||||
use Symbol qw/ gensym /;
|
||||
use IPC::Open3;
|
||||
use X11::Protocol 0.56;
|
||||
use X11::Protocol::Constants qw/ Shift Mod5 ShiftMask /;
|
||||
use X11::Protocol::WM 29;
|
||||
|
@ -593,17 +595,20 @@ sub substitute_macros {
|
|||
my $macro_servername = $self->config->{macro_servername};
|
||||
( my $servername = $svr ) =~ s/\s+//;
|
||||
$text =~ s!$macro_servername!$servername!xsmg;
|
||||
$ENV{CSSH_SERVERNAME} = $servername;
|
||||
}
|
||||
{
|
||||
my $macro_hostname = $self->config->{macro_hostname};
|
||||
my $hostname = hostfqdn();
|
||||
$text =~ s!$macro_hostname!$hostname!xsmg;
|
||||
$ENV{CSSH_HOSTNAME} = $hostname;
|
||||
}
|
||||
{
|
||||
my $macro_username = $self->config->{macro_username};
|
||||
my $username = $servers{$svr}{username};
|
||||
$username ||= getpwuid($UID);
|
||||
$text =~ s!$macro_username!$username!xsmg;
|
||||
$ENV{CSSH_USERNAME} = $username;
|
||||
}
|
||||
{
|
||||
my $macro_newline = $self->config->{macro_newline};
|
||||
|
@ -613,6 +618,54 @@ sub substitute_macros {
|
|||
my $macro_version = $self->config->{macro_version};
|
||||
my $version = $self->parent->VERSION;
|
||||
$text =~ s/$macro_version/$version/xsmg;
|
||||
$ENV{CSSH_VERSION} = $version;
|
||||
}
|
||||
|
||||
$ENV{CSSH_CONNECTION_STRING} = $servers{$svr}{connect_string};
|
||||
$ENV{CSSH_CONNECTION_PORT} = $servers{$svr}{port};
|
||||
|
||||
# Set up environment variables in the macro environment
|
||||
for my $i (qw/ 1 2 3 4 / ) {
|
||||
my $macro_user_command = 'macro_user_'.$i.'_command';
|
||||
my $macro_user = $self->config->{'macro_user_'.$i};
|
||||
|
||||
next unless $text =~ $macro_user;
|
||||
if( ! $self->config->{ $macro_user_command } ) {
|
||||
$text =~ s/$macro_user//xsmg;
|
||||
next;
|
||||
}
|
||||
|
||||
my $cmd = $self->config->{ $macro_user_command };
|
||||
|
||||
local $SIG{CHLD} = undef;
|
||||
|
||||
my $stderr_fh = gensym;
|
||||
my $stdout_fh = gensym;
|
||||
my $child_pid = eval { open3(undef, $stdout_fh, $stderr_fh, $cmd) };
|
||||
|
||||
if (my $err=$@) {
|
||||
# error message is hardcoded into open3 - tidy it up a little for our users
|
||||
$err=~ s/ at .*//;
|
||||
$err=~ s/open3: //;
|
||||
$err =~ s/( failed)/' $1/;
|
||||
$err =~ s/(exec of) /$1 '/;
|
||||
warn "Macro failure for '$macro_user_command': $err";
|
||||
next;
|
||||
}
|
||||
waitpid($child_pid, 0);
|
||||
my $cmd_rc = $? >> 8;
|
||||
|
||||
my @stdout = <$stdout_fh>;
|
||||
my @stderr = <$stderr_fh>;
|
||||
|
||||
if ( $cmd_rc > 0 || @stderr ){
|
||||
warn "Macro failure for '$macro_user_command'",$/;
|
||||
warn "Exited with error output:: @stderr" if @stderr;
|
||||
warn "Exited with non-zero return code: $cmd_rc", $/ if $cmd_rc;
|
||||
} else {
|
||||
#$self->send_text_to_all_servers( $stdout );
|
||||
return join('', @stdout);
|
||||
}
|
||||
}
|
||||
|
||||
return $text;
|
||||
|
@ -1545,6 +1598,18 @@ sub key_event {
|
|||
$self->send_text_to_all_servers(
|
||||
$self->config->{macro_username} )
|
||||
if ( $hotkey eq "key_username" );
|
||||
$self->send_text_to_all_servers(
|
||||
$self->config->{macro_user_1} )
|
||||
if ( $hotkey eq "key_user_1" );
|
||||
$self->send_text_to_all_servers(
|
||||
$self->config->{macro_user_2} )
|
||||
if ( $hotkey eq "key_user_2" );
|
||||
$self->send_text_to_all_servers(
|
||||
$self->config->{macro_user_3} )
|
||||
if ( $hotkey eq "key_user_3" );
|
||||
$self->send_text_to_all_servers(
|
||||
$self->config->{macro_user_4} )
|
||||
if ( $hotkey eq "key_user_4" );
|
||||
$self->add_host_by_name()
|
||||
if ( $hotkey eq "key_addhost" );
|
||||
$self->retile_hosts("force")
|
||||
|
|
31
t/15config.t
31
t/15config.t
|
@ -52,6 +52,10 @@ Readonly::Hash my %default_config => {
|
|||
key_macros_enable => "Alt-p",
|
||||
key_paste => "Control-v",
|
||||
key_username => "Alt-u",
|
||||
key_user_1 => "Alt-1",
|
||||
key_user_2 => "Alt-2",
|
||||
key_user_3 => "Alt-3",
|
||||
key_user_4 => "Alt-4",
|
||||
mouse_paste => "Button-2",
|
||||
auto_quit => "yes",
|
||||
auto_close => 5,
|
||||
|
@ -109,6 +113,15 @@ Readonly::Hash my %default_config => {
|
|||
macro_username => '%u',
|
||||
macro_newline => '%n',
|
||||
macro_version => '%v',
|
||||
macro_user_1 => '%1',
|
||||
macro_user_2 => '%2',
|
||||
macro_user_3 => '%3',
|
||||
macro_user_4 => '%4',
|
||||
|
||||
macro_user_1_command => '',
|
||||
macro_user_2_command => '',
|
||||
macro_user_3_command => '',
|
||||
macro_user_4_command => '',
|
||||
|
||||
max_addhost_menu_cluster_items => 6,
|
||||
menu_send_autotearoff => 0,
|
||||
|
@ -188,6 +201,9 @@ $expected{screen_reserve_left} = 100;
|
|||
$expected{screen_reserve_right} = 100;
|
||||
$expected{screen_reserve_top} = 100;
|
||||
$expected{screen_reserve_bottom} = 160;
|
||||
|
||||
# Note: the parse_config here removes the key_user_x entries
|
||||
delete( $expected{"key_user_$_"} ) for (qw/ 1 2 3 4 /);
|
||||
trap {
|
||||
$config = $config->parse_config_file( $file, );
|
||||
};
|
||||
|
@ -328,6 +344,9 @@ open( my $csshrc, '>', $ENV{HOME} . '/.csshrc' );
|
|||
print $csshrc 'auto_quit = no', $/;
|
||||
close($csshrc);
|
||||
$expected{auto_quit} = 'no';
|
||||
|
||||
# Note: the load_configs here removes the key_user_x entries
|
||||
delete( $expected{"key_user_$_"} ) for (qw/ 1 2 3 4 /);
|
||||
$config = App::ClusterSSH::Config->new();
|
||||
trap {
|
||||
$config->load_configs();
|
||||
|
@ -565,11 +584,23 @@ key_macros_enable=Alt-p
|
|||
key_paste=Control-v
|
||||
key_quit=Alt-q
|
||||
key_retilehosts=Alt-r
|
||||
key_user_1=Alt-1
|
||||
key_user_2=Alt-2
|
||||
key_user_3=Alt-3
|
||||
key_user_4=Alt-4
|
||||
key_username=Alt-u
|
||||
lang=en
|
||||
macro_hostname=%h
|
||||
macro_newline=%n
|
||||
macro_servername=%s
|
||||
macro_user_1=%1
|
||||
macro_user_1_command=
|
||||
macro_user_2=%2
|
||||
macro_user_2_command=
|
||||
macro_user_3=%3
|
||||
macro_user_3_command=
|
||||
macro_user_4=%4
|
||||
macro_user_4_command=
|
||||
macro_username=%u
|
||||
macro_version=%v
|
||||
macros_enabled=yes
|
||||
|
|
|
@ -16,6 +16,10 @@ key_paste=Control-v
|
|||
key_quit=Control-q
|
||||
key_retilehosts=Alt-r
|
||||
key_username=Alt-n
|
||||
key_user_1=Alt-1
|
||||
key_user_2=Alt-2
|
||||
key_user_3=Alt-3
|
||||
key_user_4=Alt-4
|
||||
max_host_menu_items=30
|
||||
method=ssh
|
||||
mouse_paste=Button-2
|
||||
|
|
Loading…
Add table
Reference in a new issue