mirror of
https://github.com/duncs/clusterssh.git
synced 2025-06-30 16:53:31 +00:00
Compare commits
371 commits
release-4.
...
master
Author | SHA1 | Date | |
---|---|---|---|
![]() |
9431ccc863 | ||
![]() |
cc90a9a3fb | ||
![]() |
fea0b80d48 | ||
![]() |
2d39fe46f3 | ||
![]() |
6967bceb8b | ||
![]() |
a915d3d218 | ||
![]() |
46c9bfc067 | ||
![]() |
4188dc980f | ||
![]() |
4ea91d4e68 | ||
![]() |
b302a7724f | ||
![]() |
387190e8f6 | ||
![]() |
618602f496 | ||
![]() |
cffe20e5ae | ||
![]() |
5eae528662 | ||
![]() |
00d8aa0ebd | ||
![]() |
e11cc83620 | ||
![]() |
70b4731659 | ||
![]() |
4b317108fe | ||
![]() |
0b5b5c8608 | ||
![]() |
5ddb7dbe83 | ||
![]() |
6cbec687bd | ||
![]() |
c3a2336b09 | ||
![]() |
0505630d15 | ||
![]() |
bf6e9d0648 | ||
![]() |
b35f198f08 | ||
![]() |
208889e36d | ||
![]() |
4674b20fb9 | ||
![]() |
276cab7014 | ||
![]() |
82f88450d0 | ||
![]() |
7fe7c69769 | ||
![]() |
6ec912aac2 | ||
![]() |
dab4fa2237 | ||
![]() |
900d0fabb6 | ||
![]() |
e039fef919 | ||
![]() |
805f97cd78 | ||
![]() |
40079d23d9 | ||
![]() |
6529bccdbd | ||
![]() |
dd33799eb7 | ||
![]() |
537c4c2572 | ||
![]() |
2712379084 | ||
![]() |
fb4b90886b | ||
![]() |
40d0bd4b8f | ||
![]() |
73657d2fa3 | ||
![]() |
ee3677dcd9 | ||
![]() |
7095383762 | ||
![]() |
006216faff | ||
![]() |
49828a49d0 | ||
![]() |
2fc4516740 | ||
![]() |
6fbc2a3eab | ||
![]() |
204048ecc5 | ||
![]() |
2f5b717671 | ||
![]() |
30a0817d3c | ||
![]() |
5016a136d6 | ||
![]() |
e5c33c6e13 | ||
![]() |
e857392130 | ||
![]() |
47fd5237f9 | ||
![]() |
27a714ecfa | ||
![]() |
717e7af776 | ||
![]() |
09f2671d8e | ||
![]() |
0acfe66a99 | ||
![]() |
7670b0be39 | ||
![]() |
205bf683bd | ||
![]() |
d3d6e68325 | ||
![]() |
9bbe9fb161 | ||
![]() |
0c6506e378 | ||
![]() |
f5f92105c6 | ||
![]() |
314c91d8c7 | ||
![]() |
915a55b3bd | ||
![]() |
7d515388a2 | ||
![]() |
2e0f63360b | ||
![]() |
15d3e210cf | ||
![]() |
5b827fd163 | ||
![]() |
651c756f55 | ||
![]() |
4599f3df22 | ||
![]() |
f27c42c795 | ||
![]() |
c807b52129 | ||
![]() |
5615bbc5b1 | ||
![]() |
b9731d0e35 | ||
![]() |
0fe831e25f | ||
![]() |
3816e735b1 | ||
![]() |
4dcba4d693 | ||
![]() |
3a7e832855 | ||
![]() |
3d571b2801 | ||
![]() |
7163916a99 | ||
![]() |
e0d062e20a | ||
![]() |
684b5311d5 | ||
![]() |
1c03f947bf | ||
![]() |
c50b6fff14 | ||
![]() |
4a72b1cab3 | ||
![]() |
37ce2b8a0d | ||
![]() |
d8addf58d1 | ||
![]() |
0dbf7c6808 | ||
![]() |
9a4c7714f9 | ||
![]() |
16deb34d14 | ||
![]() |
93432c1580 | ||
![]() |
f2194ecdfa | ||
![]() |
a7e066e48f | ||
![]() |
73bf10ec34 | ||
![]() |
053bd6bbd1 | ||
![]() |
d612300480 | ||
![]() |
2cfc4739b2 | ||
![]() |
df96d66150 | ||
![]() |
80113e96b0 | ||
![]() |
309ec40de0 | ||
![]() |
d9b3de5d55 | ||
![]() |
4a1f0ed5fd | ||
![]() |
d6bd23ef12 | ||
![]() |
f1446f9be3 | ||
![]() |
34f6c3e77d | ||
![]() |
fa01db1a03 | ||
![]() |
d1bc22ee22 | ||
![]() |
cd355f965d | ||
![]() |
2b9b8990b7 | ||
![]() |
3109b4a33a | ||
![]() |
593b241e6a | ||
![]() |
d822ecd81d | ||
![]() |
1805c1c9d4 | ||
![]() |
a3373813db | ||
![]() |
b49a83f9da | ||
![]() |
6f1254b3d8 | ||
![]() |
5cd27cb11f | ||
![]() |
7c9cfb1531 | ||
![]() |
30221a6c31 | ||
![]() |
d64f872b26 | ||
![]() |
ae2e986c6e | ||
![]() |
771f0a18e4 | ||
![]() |
554605d8b0 | ||
![]() |
8e1e3f8afd | ||
![]() |
689343eb24 | ||
![]() |
08fba7cc7f | ||
![]() |
eebbea81b8 | ||
![]() |
fc66ddc34b | ||
![]() |
07f59738e6 | ||
![]() |
7a08f3239e | ||
![]() |
3e3ed2c1cc | ||
![]() |
f9c6120477 | ||
![]() |
a3e8e221e7 | ||
![]() |
4665a23f09 | ||
![]() |
4266c2a06e | ||
![]() |
b9a42101f1 | ||
![]() |
60d67f911b | ||
![]() |
196d7b79bf | ||
![]() |
0fb0ba10c2 | ||
![]() |
be418fa0d0 | ||
![]() |
bc7805ca4c | ||
![]() |
4f93b8fa3e | ||
![]() |
7981edecca | ||
![]() |
41fe0714b5 | ||
![]() |
4fe7b00713 | ||
![]() |
469897d4c5 | ||
![]() |
9f6c000592 | ||
![]() |
29762f2868 | ||
![]() |
067bab1894 | ||
![]() |
142d4ddd66 | ||
![]() |
7974687cfb | ||
![]() |
7822d337f7 | ||
![]() |
54a0a086eb | ||
![]() |
ab1dde0e8c | ||
![]() |
3467c5191d | ||
![]() |
95d7bfbdce | ||
![]() |
eb586e1281 | ||
![]() |
d3b8bc0b0e | ||
![]() |
63b83a176c | ||
![]() |
b7b7ca70ac | ||
![]() |
64b414bdbe | ||
![]() |
c83e9e785f | ||
![]() |
3002314e92 | ||
![]() |
b72b748eff | ||
![]() |
d41c2b0400 | ||
![]() |
55c91fe991 | ||
![]() |
ed829083c2 | ||
![]() |
ede9868d55 | ||
![]() |
9cbd28546a | ||
![]() |
08adb3766b | ||
![]() |
33fa9b9911 | ||
![]() |
0ecf12256d | ||
![]() |
8b8a692b6c | ||
![]() |
08d7fead03 | ||
![]() |
00c4766e20 | ||
![]() |
bce8c79f10 | ||
![]() |
454f30978d | ||
![]() |
754a7137b6 | ||
![]() |
e5622cda99 | ||
![]() |
596ef164d3 | ||
![]() |
658a36b7e6 | ||
![]() |
3b22f44680 | ||
![]() |
69c8480eb9 | ||
![]() |
71817cc0e8 | ||
![]() |
9061154667 | ||
![]() |
dd95e94e7f | ||
![]() |
ceda2524cf | ||
![]() |
1c6a709f3a | ||
![]() |
b0366e8469 | ||
![]() |
6b752e583b | ||
![]() |
babbaa86a3 | ||
![]() |
b330457f99 | ||
![]() |
b9738f7142 | ||
![]() |
c5c2c4fc0e | ||
![]() |
31dcf8d546 | ||
![]() |
7ae92d4c2c | ||
![]() |
0a307da3ac | ||
![]() |
7e55006acd | ||
![]() |
736eaed8c5 | ||
![]() |
8c20689d24 | ||
![]() |
41162764c2 | ||
![]() |
1a103722f3 | ||
![]() |
3d1ae7c38e | ||
![]() |
a2456461f3 | ||
![]() |
dc041e730d | ||
![]() |
7706fdc45e | ||
![]() |
9431f57a60 | ||
![]() |
fb475e27f4 | ||
![]() |
96c73a0080 | ||
![]() |
54499686bf | ||
![]() |
d5fae40c2a | ||
![]() |
e87192db9b | ||
![]() |
0fb709adb8 | ||
![]() |
43d4f1d246 | ||
![]() |
3f79f1ff54 | ||
![]() |
0358721c67 | ||
![]() |
91a2b70b33 | ||
![]() |
1a3d5495d6 | ||
![]() |
ffe6a9d283 | ||
![]() |
3fcc001cca | ||
![]() |
7808bd8e20 | ||
![]() |
4c38c4d1f4 | ||
![]() |
4157d9f3e2 | ||
![]() |
2f26815445 | ||
![]() |
5e8f1b1166 | ||
![]() |
502c3888b0 | ||
![]() |
b4edd6abdb | ||
![]() |
c0f2b8af41 | ||
![]() |
1d492e3ba2 | ||
![]() |
9046e4b088 | ||
![]() |
94d3bca20e | ||
![]() |
e1df115736 | ||
![]() |
595cfab20c | ||
![]() |
efcc12e1d5 | ||
![]() |
dda4297711 | ||
![]() |
b77830dea5 | ||
![]() |
153709b220 | ||
![]() |
5fad534ef0 | ||
![]() |
e83887c9b7 | ||
![]() |
7136c515a6 | ||
![]() |
56d5a163df | ||
![]() |
264391660d | ||
![]() |
b288fa217b | ||
![]() |
3e06edfbe5 | ||
![]() |
ed49237f52 | ||
![]() |
4b02448f0a | ||
![]() |
576ace2e3d | ||
![]() |
f23821af6f | ||
![]() |
61449301d0 | ||
![]() |
b002b1aac2 | ||
![]() |
5fbc452d29 | ||
![]() |
c53eedaf1c | ||
![]() |
ef13feb390 | ||
![]() |
4045bb467b | ||
![]() |
74720d6b2f | ||
![]() |
6f30f9976e | ||
![]() |
fb4d991053 | ||
![]() |
457c3e8e1c | ||
![]() |
e528584eb0 | ||
![]() |
9b21aaaa61 | ||
![]() |
97ec81692a | ||
![]() |
76b8096dcc | ||
![]() |
d684b077fd | ||
![]() |
fdf4d0c1dd | ||
![]() |
4971005d17 | ||
![]() |
02942e7e24 | ||
![]() |
6bf4b932ee | ||
![]() |
f169e544fd | ||
![]() |
3cfb83c0d6 | ||
![]() |
c4211a1ee5 | ||
![]() |
12587955b2 | ||
![]() |
56dfd55d30 | ||
![]() |
5d5634c4cc | ||
![]() |
f8ed9da353 | ||
![]() |
d9446aa28a | ||
![]() |
296580227a | ||
![]() |
c07d283958 | ||
![]() |
9962aa08f8 | ||
![]() |
8aaea928d7 | ||
![]() |
26e783be1c | ||
![]() |
a93b3f3cac | ||
![]() |
f88353d3dd | ||
![]() |
bc45e0cac7 | ||
![]() |
b374754129 | ||
![]() |
93146a023d | ||
![]() |
f22bce3cb1 | ||
![]() |
72668c128f | ||
![]() |
395a35e018 | ||
![]() |
05554f1a1f | ||
![]() |
d424b59228 | ||
![]() |
ee9ec5a366 | ||
![]() |
e7694e836e | ||
![]() |
2e74fd5d3b | ||
![]() |
c0ac1169eb | ||
![]() |
70d2cfcb98 | ||
![]() |
d7d9f83b15 | ||
![]() |
085803c328 | ||
![]() |
c6747288d5 | ||
![]() |
3e2392e9b6 | ||
![]() |
0853d8fee6 | ||
![]() |
d439a777b3 | ||
![]() |
83cfd73a11 | ||
![]() |
858112c072 | ||
![]() |
7efebc30b9 | ||
![]() |
0b9d1dbb97 | ||
![]() |
a0b4514176 | ||
![]() |
8a445a32ba | ||
![]() |
977ae78c6f | ||
![]() |
3987586e3f | ||
![]() |
dbfa2733fd | ||
![]() |
3416ab1288 | ||
![]() |
3cffd71b2f | ||
![]() |
2f9779d8f5 | ||
![]() |
e6ed822a43 | ||
![]() |
e54a8cf2bb | ||
![]() |
36d100d62d | ||
![]() |
97884dd03e | ||
![]() |
666a1c0306 | ||
![]() |
f39ffcb9e4 | ||
![]() |
5c31d13f83 | ||
![]() |
4abbf5e494 | ||
![]() |
c7853ce73a | ||
![]() |
e5c8272520 | ||
![]() |
6113f5d83a | ||
![]() |
5b8cfc9e4d | ||
![]() |
374775bf87 | ||
![]() |
13442fb156 | ||
![]() |
a802b09964 | ||
![]() |
352a2108dc | ||
![]() |
8569cdaca5 | ||
![]() |
be4093f728 | ||
![]() |
b2156d8170 | ||
![]() |
31d831bb0c | ||
![]() |
bdfd32c12d | ||
![]() |
e0b5514341 | ||
![]() |
b33f3ffb13 | ||
![]() |
8990956ad4 | ||
![]() |
ed405b9c98 | ||
![]() |
1edf8088f9 | ||
![]() |
526cc24860 | ||
![]() |
5b71abdcce | ||
![]() |
671c231992 | ||
![]() |
88d4946596 | ||
![]() |
29297fa116 | ||
![]() |
da8dc00d47 | ||
![]() |
305a6f3535 | ||
![]() |
b4f2f56a29 | ||
![]() |
8c56a7a8e1 | ||
![]() |
b54863993d | ||
![]() |
31d2d6dd07 | ||
![]() |
b506891540 | ||
![]() |
61a04ac3d2 | ||
![]() |
155b861e08 | ||
![]() |
74151fe5e0 | ||
![]() |
6924bca28d | ||
![]() |
f8723f2dce | ||
![]() |
437b8c4867 | ||
![]() |
77e3c28624 | ||
![]() |
17cbd36d7c | ||
![]() |
ed2940d92a | ||
![]() |
cfaf930f16 | ||
![]() |
f344270921 | ||
![]() |
cd1abe15b9 | ||
![]() |
161fba4dac | ||
![]() |
ac41ffeb2b | ||
![]() |
58bd88a023 | ||
![]() |
56faa0ac30 |
54 changed files with 7736 additions and 4288 deletions
68
.github/workflows/dzil_tester.yml
vendored
Normal file
68
.github/workflows/dzil_tester.yml
vendored
Normal file
|
@ -0,0 +1,68 @@
|
|||
name: CI test builds
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: '*'
|
||||
pull_request:
|
||||
branches: '*'
|
||||
|
||||
jobs:
|
||||
perl-job:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
perl-version:
|
||||
- 'devel'
|
||||
- 'latest'
|
||||
- '5.40'
|
||||
- '5.38'
|
||||
- '5.36'
|
||||
- '5.34'
|
||||
- '5.32'
|
||||
- '5.30'
|
||||
- '5.28'
|
||||
- '5.26'
|
||||
- '5.24'
|
||||
- '5.22'
|
||||
- '5.20'
|
||||
- '5.18'
|
||||
- '5.16'
|
||||
include:
|
||||
- perl-version: '5.38'
|
||||
os: ubuntu-latest
|
||||
coverage: true
|
||||
container:
|
||||
image: perldocker/perl-tester:${{ matrix.perl-version }}
|
||||
|
||||
name: Perl ${{ matrix.perl-version }}
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@main
|
||||
- name: Amend PATH
|
||||
run: echo "${GITHUB_WORKSPACE}/t/bin" >> $GITHUB_PATH
|
||||
- name: Current env
|
||||
run: env
|
||||
- name: Perl info
|
||||
run: perl -V
|
||||
- name: CPAN test modules
|
||||
run: cpanm -n Pod::Coverage::TrustPod Test::Perl::Critic Test::Pod::Coverage Test::Pod Test::Trap
|
||||
- name: CPAN build modules
|
||||
run: cpanm -n Tk X11::Protocol X11::Protocol::Other
|
||||
- name: Initial Build
|
||||
run: perl Build.PL
|
||||
- name: Build the MANIFEST
|
||||
run: perl Build manifest
|
||||
- name: Test suite
|
||||
if: ${{ !matrix.coverage }}
|
||||
run: perl Build test
|
||||
env:
|
||||
RELEASE_TESTING: 1
|
||||
AUTHOR_TESTING: 1
|
||||
- name: Coverage tests
|
||||
if: ${{ matrix.coverage }}
|
||||
run: perl Build test
|
||||
env:
|
||||
COVERAGE: 1
|
||||
RELEASE_TESTING: 1
|
||||
AUTHOR_TESTING: 1
|
24
.gitignore
vendored
24
.gitignore
vendored
|
@ -1,11 +1,17 @@
|
|||
/App-*
|
||||
*.bak
|
||||
/bin
|
||||
/blib/
|
||||
/_build/
|
||||
/.build/
|
||||
/Build
|
||||
Build.PL.orig
|
||||
Build.PL.x
|
||||
/cover_db/
|
||||
/Makefile
|
||||
/MANIFEST.bak
|
||||
/MYMETA.json
|
||||
/MYMETA.yml
|
||||
/pm_to_blib
|
||||
*.swp
|
||||
*.tar.gz
|
||||
Build
|
||||
MANIFEST.bak
|
||||
MYMETA.json
|
||||
MYMETA.yml
|
||||
Makefile
|
||||
_build/
|
||||
blib/
|
||||
cover_db/
|
||||
pm_to_blib
|
||||
|
|
73
Build.PL
73
Build.PL
|
@ -1,45 +1,38 @@
|
|||
use strict;
|
||||
use warnings;
|
||||
use lib 'inc';
|
||||
|
||||
use Module::Build;
|
||||
require Module::Build;
|
||||
|
||||
my $build = Module::Build->new(
|
||||
meta_merge => {
|
||||
resources => {
|
||||
Repository => [
|
||||
'http://clusterssh.git.sourceforge.net/',
|
||||
'http://github.com/duncs/clusterssh',
|
||||
],
|
||||
bugtracker => 'http://sourceforge.net/tracker/?group_id=89139',
|
||||
homepage => 'http://clusterssh.sourceforge.net/',
|
||||
},
|
||||
my %module_build_args = (
|
||||
module_name => 'App::ClusterSSH',
|
||||
dist_abstract => "Cluster administration tool",
|
||||
##{ $plugin->get_prereqs(1) ##}
|
||||
##{ $plugin->get_default('share_dir') ##}
|
||||
script_files => [
|
||||
'bin/cssh', 'bin/csftp',
|
||||
'bin/ccon', 'bin/crsh',
|
||||
'bin/ctel', 'bin/clusterssh_bash_completion.dist'
|
||||
],
|
||||
PL_files => {
|
||||
'bin_PL/_build_docs' => [
|
||||
'bin/cssh', 'bin/csftp',
|
||||
'bin/ccon', 'bin/crsh',
|
||||
'bin/ctel', 'bin/clusterssh_bash_completion.dist'
|
||||
],
|
||||
},
|
||||
module_name => 'App::ClusterSSH',
|
||||
license => 'perl',
|
||||
dist_author => q{Duncan Ferguson <duncan_j_ferguson@yahoo.co.uk>},
|
||||
dist_version_from => 'lib/App/ClusterSSH.pm',
|
||||
requires => {
|
||||
'version' => '0',
|
||||
'Tk' => '800.022',
|
||||
'X11::Protocol' => '0.56',
|
||||
'Locale::Maketext' => 0,
|
||||
'Exception::Class' => '1.31',
|
||||
'Try::Tiny' => 0,
|
||||
},
|
||||
build_requires => {
|
||||
'Test::Pod::Coverage' => 0,
|
||||
'Test::Pod' => 0,
|
||||
'Test::Trap' => 0,
|
||||
'Readonly' => 0,
|
||||
'File::Which' => 0,
|
||||
'File::Temp' => 0,
|
||||
'Test::DistManifest' => 0,
|
||||
'Test::Differences' => 0,
|
||||
},
|
||||
configure_requires => { 'Module::Build' => 0, },
|
||||
add_to_cleanup => ['App-ClusterSSH-*'],
|
||||
create_makefile_pl => 'traditional',
|
||||
script_files => 'bin',
|
||||
);
|
||||
|
||||
$build->create_build_script;
|
||||
unless ( eval { Module::Build->VERSION(0.4004) } ) {
|
||||
my $tr = delete $module_build_args{test_requires};
|
||||
my $br = $module_build_args{build_requires};
|
||||
for my $mod ( keys %$tr ) {
|
||||
if ( exists $br->{$mod} ) {
|
||||
$br->{$mod} = $tr->{$mod} if $tr->{$mod} > $br->{$mod};
|
||||
}
|
||||
else {
|
||||
$br->{$mod} = $tr->{$mod};
|
||||
}
|
||||
}
|
||||
} # end unless Module::Build is 0.4004 or newer
|
||||
|
||||
my $builder = Module::Build->new(%module_build_args);
|
||||
$builder->create_build_script;
|
||||
|
|
693
Changes
693
Changes
|
@ -1,4 +1,161 @@
|
|||
2014-01-13 Duncan Ferguson <duncan_ferguson@user.sf.net> - v4.02_02
|
||||
Revision history for {{$dist->name}}
|
||||
|
||||
4.18 2024-10-19 Duncan Ferguson <duncan_ferguson@user.sf.net>
|
||||
- Re-release due to poor release upload to CPAN
|
||||
|
||||
4.17 2024-10-16 Duncan Ferguson <duncan_ferguson@user.sf.net>
|
||||
- Swap the hostname lookup macro from DNS to using the system hostname (Github issue #158)
|
||||
- Swap from using Travis-CI to Github Actions
|
||||
- Fix tests on perl 5.38 and 5.40 (Github Issue #153)
|
||||
|
||||
4.16 2020-06-20 Duncan Ferguson <duncan_ferguson@user.sf.net>
|
||||
- Further fix for 'resolve_names' error when adding hosts via the UI
|
||||
- Fix missing space separator for ssh_args (thanks to Petr Vorel)
|
||||
|
||||
4.15 2020-05-18 Duncan Ferguson <duncan_ferguson@user.sf.net>
|
||||
- Include all utilies within each man page
|
||||
- Add in 'command_pre' and 'command_post' configuration options
|
||||
- Fix 'Add Host' menu error finding 'resolved_names'
|
||||
- Ensure lib path is added to range tests to find the libraries
|
||||
- Mark permission test as TODO as it appears to be inconsistent
|
||||
|
||||
4.14 2019-08-21 Duncan Ferguson <duncan_ferguson@user.sf.net>
|
||||
- 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
|
||||
- Fix excess test output when Sort::Naturally isn't installed
|
||||
|
||||
4.13.2_01 2018-11-24 Duncan Ferguson <duncan_ferguson@user.sf.net>
|
||||
- Move all Tk code into its own module as-is
|
||||
- Fix for 'bad pad value "3m"' error when using Tk 804.034
|
||||
- Update to Perl::Tidy 20181117
|
||||
- Convert to using Dist::Zilla
|
||||
|
||||
4.13.2 2018-03-14 Duncan Ferguson <duncan_ferguson@user.sf.net>
|
||||
- Fix for running builds in parallel
|
||||
- Improvements to SUPPORT and REPORTING BUGS sections in documentation
|
||||
|
||||
4.13.1 2018-03-05 Duncan Ferguson <duncan_ferguson@user.sf.net>
|
||||
- Minor update to fix failing tests due to 3rd party perltidy changes
|
||||
|
||||
4.13 2017-12-27 Duncan Ferguson <duncan_ferguson@user.sf.net>
|
||||
- Ensure ssh_args is keep unset if it is emptied in the configuration file
|
||||
- Obey configured console position (Debian bug 758215) (Github issue #100)
|
||||
|
||||
4.12 2017-12-23 Duncan Ferguson <duncan_ferguson@user.sf.net>
|
||||
- Fix 'undefined value' error
|
||||
|
||||
4.11 2017-12-22 Duncan Ferguson <duncan_ferguson@user.sf.net>
|
||||
- Fix for multiple range expansion, as in 'h{a,b}{1,2}' (Github issue #97) (Thanks to lazyfrosch)
|
||||
- Upgrade Perl::Tidy requirement to version 20171214 (Github issue #99) (Thanks to eserte)
|
||||
- Add in 'external command pipe' to allow for some commands being passed in from the command line
|
||||
|
||||
4.10_02 2017-08-08 Duncan Ferguson <duncan_ferguson@user.sf.net>
|
||||
- Include coverage tests in the resources
|
||||
- Include the version of cssh in the utility documentation and README
|
||||
- Fix dashes (-) not being accepted in hostname range expansion (Github issue #89)
|
||||
- Amend ranges to work on ports, FQDN's and IP addresses
|
||||
- Fix bug tracker links in the main documentation (Github issue #92)
|
||||
- New options to specify --rows, --columns and --fillscreen (Github pull request #88) (Thanks to AsharLohmar)
|
||||
|
||||
4.10_01 2017-04-12 Duncan Ferguson <duncan_ferguson@user.sf.net>
|
||||
- Allow 'include' directives when reading SSH configuration files (Github issue #77) (thanks to Azenet)
|
||||
- Generate README when creating the distribution from cssh man page so www.cpan.org and www.metacpan.org can display documentation
|
||||
|
||||
4.09 2017-03-11 Duncan Ferguson <duncan_ferguson@user.sf.net>
|
||||
- Add perl-5.24 Travis-CI automated testing config
|
||||
- Correct a logic bug around the --debug option (Github issue #75)
|
||||
- Fix 'Re-add closed windows' not using the correct username (Github issue #72)
|
||||
- Update copyright year
|
||||
- Make WM decorations algorithm configurable as causes problems on some systems (Debian bug 842965, re Github pull request #66) (thanks to Tony Mancill)
|
||||
|
||||
4.08 2016-10-18 Duncan Ferguson <duncan_ferguson@user.sf.net>
|
||||
- Add perl-5.8, 5.10 and 5.12 to Travis-CI automated testing
|
||||
- Fix building and testing on perl-5.8.9
|
||||
- Improve testing on systems that do not have xterm installed
|
||||
- Take into account WM decorations when tiling (Github pull request #66) (thanks to Andrew Stevenson)
|
||||
- Add option in the config file to hide the menu (Github issue #69)
|
||||
- Add 'unique_servers' into the configuration file to match command line option (Github issue #70)
|
||||
|
||||
4.07 2016-04-30 Duncan Ferguson <duncan_ferguson@user.sf.net>
|
||||
- Fixed tests on systems where bash is not installed in /bin/bash (Github issue #60)
|
||||
- Include link to travis-ci site in release emails for automated build and test reports
|
||||
- Rework hostname expansion to be pure-perl rather than relying on the bash shell (Github issue #53)
|
||||
|
||||
4.06 2016-03-26 Duncan Ferguson <duncan_ferguson@user.sf.net>
|
||||
- Failure to find the terminal binary should not be fatal
|
||||
- Fix processing of '--extra_tag_file' and its configuration item (Github issue #51)
|
||||
- Add bash shell expansion on host names containing a '{' character (Github issue #53)
|
||||
- Fix tests when running on a server without xterm installed (such as Travis CI via GitHub)
|
||||
- Expand $HOME and ~ correctly when looking for files (thanks to Andrew Stevenson)
|
||||
- Typo correction in README (thanks to Ankit Vadehra)
|
||||
|
||||
4.05 2015-11-28 Duncan Ferguson <duncan_ferguson@user.sf.net>
|
||||
- Change default key_quit from 'Control-q' to 'Alt-q' (Github issue #50)
|
||||
- Amend tests to always use C locale as some error messages are hardcoded in English (Github issue #49)
|
||||
|
||||
4.04_01 2015-11-21 Duncan Ferguson <duncan_ferguson@user.sf.net>
|
||||
- Ensure documentation is generated using same perl as the build (Github issue #45)
|
||||
- Pass '--action' through macro parsing (Github issue #42)
|
||||
- Workaround for glitch in KDE where windows can become unmoveable (Github issue #46) (thanks to Brandon Perkins)
|
||||
- Add in '--quiet | -Q ' option to reduce output in certian scenarios
|
||||
- Add in 'csftp' command
|
||||
|
||||
4.04 2015-11-03 Duncan Ferguson <duncan_ferguson@user.sf.net>
|
||||
- Include bash completion script in distribution (Github issue #29)
|
||||
- Allow re-adding closed session (Github issue #27 - thanks to Andrew Stevenson)
|
||||
- Allow sorting windows in natural order (Github issue #28 - thanks to Andrew Stevenson)
|
||||
- Fix links in metadata files to trackers (Github issue #41)
|
||||
- Fix ctel and ccon not working correctly (Github issue #35)
|
||||
- Amend t/10host.t to use a random hostname to prevent clashes (Github issue #23)
|
||||
- Amend copyright message in README to match all other files for the perl license (Github issue #44)
|
||||
|
||||
4.03_06 2015-01-31 Duncan Ferguson <duncan_ferguson@user.sf.net>
|
||||
- Remove references to 'logmsg' preventing the history window from working (thanks to Andrew Stevenson)
|
||||
|
||||
4.03_05 2014-12-20 Duncan Ferguson <duncan_ferguson@user.sf.net>
|
||||
- Fix options parsing tests picked up via cpantesters on different version of perl
|
||||
|
||||
4.03_04 2014-12-12 Duncan Ferguson <duncan_ferguson@user.sf.net>
|
||||
- Do not use system perl but whatever is found in PATH (to stop breaking perlbrew based builds)
|
||||
- Warn when the configured terminal isn't installed/found
|
||||
- Don't show 'Opening to:' when no servers are given
|
||||
|
||||
4.03_03 2014-09-28 Duncan Ferguson <duncan_ferguson@user.sf.net>
|
||||
- Force tests to have English locale when user has something else set (Github issue: 10) (thanks to Emanuele Tomasi)
|
||||
- Skip permissions check test when run as root as the results are invalid (Github issue: 11) (thanks to Deny Dias)
|
||||
- Ensure config file option for ssh_args is not lost when options is not used on command line (Github issue: 14)
|
||||
- New Send menu option to send a numeric value between 1 and 1024 (thanks to cqexbesd)
|
||||
- Remove all history when history window closed (thanks to Bill Rushmore)
|
||||
|
||||
4.03_02 2014-08-10 Duncan Ferguson <duncan_ferguson@user.sf.net>
|
||||
- Fix behaviour when external cluster command is not defined or doesn't exist
|
||||
|
||||
4.03_01 2014-07-09 Duncan Ferguson <duncan_ferguson@user.sf.net>
|
||||
- Amended host parsing to include alternative IPv6 address port definitions, e.g. 1::2::3::4/5567
|
||||
- List available external tags with -L option and also add into 'Add Host' in UI
|
||||
[NOTE: Some options have changed!]
|
||||
- Rework options code
|
||||
|
||||
4.02_05 0000-00-00 Duncan Ferguson <duncan_ferguson@user.sf.net> (unreleased)
|
||||
- Add in 'Set all active' and 'Set half active' host menu options (thanks to Andrew Stevenson)
|
||||
|
||||
4.02_04 2014-05-17 Duncan Ferguson <duncan_ferguson@user.sf.net>
|
||||
- Amend 'Changes' file format to match CPAN specs (see CPAN::Changes)
|
||||
- Correct autoclose short option to what is actually used (Github issue 4) (thanks to Simon Fraser)
|
||||
- Fix 'use_all_a_records' option (Github issue: 5) (thanks to Simon Fraser)
|
||||
- Fix 'title' option (thanks to Barry Roberts)
|
||||
- Fix 'Add host or cluster' window to contain cluster names
|
||||
|
||||
4.02_03 2014-01-31 Duncan Ferguson <duncan_ferguson@user.sf.net>
|
||||
- Fix 'File->Show History' (Sf support request 41)
|
||||
- Amend 'tag-file' short option to 'r' to avoid option clash
|
||||
|
||||
4.02_02 2014-01-13 Duncan Ferguson <duncan_ferguson@user.sf.net>
|
||||
- Fixed macros (%u, %s, %h, %n) not doing multiple replacements
|
||||
- Add in key shortcut for username macro (ALT-u)
|
||||
- Add in key shortcut for local hostname macro (ALT-l)
|
||||
|
@ -7,392 +164,390 @@
|
|||
- Fixed the default cluster not being opened
|
||||
- Add in toggle for macros
|
||||
|
||||
2013-04-16 Duncan Ferguson <duncan_ferguson@user.sf.net> - v4.02_01
|
||||
4.02_01 2013-04-16 Duncan Ferguson <duncan_ferguson@user.sf.net>
|
||||
- Refactured file loading code
|
||||
- Add in 'tags' file handling
|
||||
- Fix bug whereby cluster files were read in multiple times
|
||||
- Add in resolving tags by external command
|
||||
- Fix library path on bin/cssh (Sf bug 3610601)
|
||||
|
||||
2013-03-05 Duncan Ferguson <duncan_ferguson@user.sf.net> - v4.01_05
|
||||
4.01_05 2013-03-05 Duncan Ferguson <duncan_ferguson@user.sf.net>
|
||||
- New option (-m, --unique-servers) to remove repeated servers when opening terminals (Thanks to Oliver Meissner)
|
||||
- Drop MYMETA.yml and .json files from the distribution
|
||||
- Do not set default user name to prevent overriding ssh configuration
|
||||
|
||||
2013-02-26 Duncan Ferguson <duncan_ferguson@user.sf.net> - v4.01_04
|
||||
4.01_04 2013-02-26 Duncan Ferguson <duncan_ferguson@user.sf.net>
|
||||
- Fixed 'ccon' not calling the correct command (Sf bug 3605002)
|
||||
- Fixed clusters not being defined correctly within the .clusterssh/config file (Sf bug 3605675)
|
||||
|
||||
2013-02-15 Duncan Ferguson <duncan_ferguson@user.sf.net> - v4.01_03
|
||||
* Correct documentation for references to $HOME/.clusterssh/config
|
||||
* Re-add user back into the configurartion file
|
||||
* Add in missing newline for some error messages
|
||||
* Allow the path to rsh/ssh/telnet to be defined in the configuration file
|
||||
* Move .csshrc to .csshrc.DISABLED since it should no longer be used
|
||||
* Error emitted when adding a host via the "Hosts" drop-down (Debian bug ID #578208)
|
||||
* Pastes uses a strange keyboard layout (Debian bug ID #364565)
|
||||
* Cope with being invoked by 'clusterssh' (Debian bug ID #644368)
|
||||
* Fix migration of .csshrc when not working as expected (Debian bug ID #673507)
|
||||
* Remove doc references to 'always_tile' as renamed 'window_tiling' (Debian bug ID #697371)
|
||||
* Updated manpage whatis entries (patch by Tony Mancill)
|
||||
* Fix watch line expression to catch 4.x series tarballs (Debian patch LP ID #1076897)
|
||||
* Allow tests to pass successfully when run as root
|
||||
* Fix cssh starting if xterm is not installed (Sf bug 3494988)
|
||||
* Set WM_CLASS on windows to 'cssh' (Sf bug 3187736)
|
||||
4.01_03 2013-02-15 Duncan Ferguson <duncan_ferguson@user.sf.net>
|
||||
- Correct documentation for references to $HOME/.clusterssh/config
|
||||
- Re-add user back into the configurartion file
|
||||
- Add in missing newline for some error messages
|
||||
- Allow the path to rsh/ssh/telnet to be defined in the configuration file
|
||||
- Move .csshrc to .csshrc.DISABLED since it should no longer be used
|
||||
- Error emitted when adding a host via the "Hosts" drop-down (Debian bug ID #578208)
|
||||
- Pastes uses a strange keyboard layout (Debian bug ID #364565)
|
||||
- Cope with being invoked by 'clusterssh' (Debian bug ID #644368)
|
||||
- Fix migration of .csshrc when not working as expected (Debian bug ID #673507)
|
||||
- Remove doc references to 'always_tile' as renamed 'window_tiling' (Debian bug ID #697371)
|
||||
- Updated manpage whatis entries (patch by Tony Mancill)
|
||||
- Fix watch line expression to catch 4.x series tarballs (Debian patch LP ID #1076897)
|
||||
- Allow tests to pass successfully when run as root
|
||||
- Fix cssh starting if xterm is not installed (Sf bug 3494988)
|
||||
- Set WM_CLASS on windows to 'cssh' (Sf bug 3187736)
|
||||
|
||||
2012-12-09 Duncan Ferguson <duncan_ferguson@user.sf.net> - v4.01_02
|
||||
* Fix logic when using 'autoclose' on the command line or config file
|
||||
* Fix $HOME/.clusterssh/clusters being read in
|
||||
* Fix 'ctel', 'crsh' and 'ccon'so they work as expected
|
||||
4.01_02 2012-12-09 Duncan Ferguson <duncan_ferguson@user.sf.net>
|
||||
- Fix logic when using 'autoclose' on the command line or config file
|
||||
- Fix $HOME/.clusterssh/clusters being read in
|
||||
- Fix 'ctel', 'crsh' and 'ccon'so they work as expected
|
||||
|
||||
2011-12-09 Duncan Ferguson <duncan_ferguson@user.sf.net> - v4.01_01
|
||||
* Include missing files from release tarballs
|
||||
4.01_01 2011-12-09 Duncan Ferguson <duncan_ferguson@user.sf.net>
|
||||
- Include missing files from release tarballs
|
||||
|
||||
2011-12-03 Duncan Ferguson <duncan_ferguson@user.sf.net> - v4.01_00
|
||||
* Start switching code to use Exception::Class
|
||||
* Moved config file from $HOME/.csshrc file to $HOME/.clusterssh directory
|
||||
* Rework config handling into a module
|
||||
* Rework cluster handling into a module
|
||||
* Added 'autoclose' functionality - see docs
|
||||
* Allow "-a 'cmd ; cmd'" to work for multiple remote commands
|
||||
4.01_00 2011-12-03 Duncan Ferguson <duncan_ferguson@user.sf.net>
|
||||
- Start switching code to use Exception::Class
|
||||
- Moved config file from $HOME/.csshrc file to $HOME/.clusterssh directory
|
||||
- Rework config handling into a module
|
||||
- Rework cluster handling into a module
|
||||
- Added 'autoclose' functionality - see docs
|
||||
- Allow "-a 'cmd ; cmd'" to work for multiple remote commands
|
||||
|
||||
2011-07-28 Duncan Ferguson <duncan_ferguson@user.sf.net> - v4.00_11
|
||||
* Fix '-l <username>' option (SF bug 3380675)
|
||||
4.00_11 2011-07-28 Duncan Ferguson <duncan_ferguson@user.sf.net>
|
||||
- Fix '-l <username>' option (SF bug 3380675)
|
||||
|
||||
2011-07-08 Duncan Ferguson <duncan_ferguson@user.sf.net> - v4.00_10
|
||||
* Fix 'uninitialised error' message
|
||||
4.00_10 2011-07-08 Duncan Ferguson <duncan_ferguson@user.sf.net>
|
||||
- Fix 'uninitialised error' message
|
||||
|
||||
2011-06-30 Duncan Ferguson <duncan_ferguson@user.sf.net> - v4.00_09
|
||||
* Cater for missing 'pod2text' command (Thanks to Sami Kerola)
|
||||
* Fix 'uninitialised variable' error
|
||||
* Added 'ccon' command (Thanks to Brandon Perkins)
|
||||
4.00_09 2011-06-30 Duncan Ferguson <duncan_ferguson@user.sf.net>
|
||||
- Cater for missing 'pod2text' command (Thanks to Sami Kerola)
|
||||
- Fix 'uninitialised variable' error
|
||||
- Added 'ccon' command (Thanks to Brandon Perkins)
|
||||
|
||||
2011-04-01 Duncan Ferguson <duncan_ferguson@user.sf.net> - v4.00_08
|
||||
* Amend all L<xx> links to prevent build breakage on cygwin (Sf bug 3115635)
|
||||
4.00_08 2011-04-01 Duncan Ferguson <duncan_ferguson@user.sf.net>
|
||||
- Amend all L<xx> links to prevent build breakage on cygwin (Sf bug 3115635)
|
||||
|
||||
2011-01-24 Duncan Ferguson <duncan_ferguson@user.sf.net> - v4.00_07
|
||||
* Fix for parsing config files with empty values (Stefan Steiner)
|
||||
* Reinstate acting on '-l username' option (reported by Ryan Brown)
|
||||
4.00_07 2011-01-24 Duncan Ferguson <duncan_ferguson@user.sf.net>
|
||||
- Fix for parsing config files with empty values (Stefan Steiner)
|
||||
- Reinstate acting on '-l username' option (reported by Ryan Brown)
|
||||
|
||||
2010-09-20 Duncan Ferguson <duncan_ferguson@user.sf.net> - v4.00_06
|
||||
* Fix test error on 5.8.8 (reported by Wei Wang)
|
||||
* Added '--list', '-L' to list available cluster tags (idea from Markus Manzke)
|
||||
* Fix terminal size only set on last windows (Sf bug 3061999)
|
||||
* Added '--use_all_a_records' (Simon Fraser)
|
||||
4.00_06 2010-09-20 Duncan Ferguson <duncan_ferguson@user.sf.net>
|
||||
- Fix test error on 5.8.8 (reported by Wei Wang)
|
||||
- Added '--list', '-L' to list available cluster tags (idea from Markus Manzke)
|
||||
- Fix terminal size only set on last windows (Sf bug 3061999)
|
||||
- Added '--use_all_a_records' (Simon Fraser)
|
||||
|
||||
2010-06-20 Duncan Ferguson <duncan_ferguson@user.sf.net> - v4.00_05
|
||||
4.00_05 2010-06-20 Duncan Ferguson <duncan_ferguson@user.sf.net>
|
||||
|
||||
* Tidy up pod for whatis errors
|
||||
* Amend copyright years and text to be consistent
|
||||
* Include missing buld prereq (Test::Trap)
|
||||
* Correct '--font, -f' in cssh documentation
|
||||
- Tidy up pod for whatis errors
|
||||
- Amend copyright years and text to be consistent
|
||||
- Include missing buld prereq (Test::Trap)
|
||||
- Correct '--font, -f' in cssh documentation
|
||||
- Thanks to Tony Mancill for reporting these errors
|
||||
|
||||
2010-06-20 Duncan Ferguson <duncan_ferguson@user.sf.net> - v4.00_04
|
||||
4.00_04 2010-06-20 Duncan Ferguson <duncan_ferguson@user.sf.net>
|
||||
|
||||
* Update MANIFEST file to ensure all correct files are included in release
|
||||
- Update MANIFEST file to ensure all correct files are included in release
|
||||
|
||||
2010-06-20 Duncan Ferguson <duncan_ferguson@user.sf.net> - v4.00_03
|
||||
4.00_03 2010-06-20 Duncan Ferguson <duncan_ferguson@user.sf.net>
|
||||
|
||||
* Fix silly type in code/tests
|
||||
- Fix silly type in code/tests
|
||||
|
||||
2010-06-19 Duncan Ferguson <duncan_ferguson@user.sf.net> - v4.00_02
|
||||
4.00_02 2010-06-19 Duncan Ferguson <duncan_ferguson@user.sf.net>
|
||||
|
||||
* Add in bugtracker and homepage resources to Build.PL file
|
||||
* Bring new module App::ClusterSSH::Host into play for parsing host strings
|
||||
* Patch to override font used on command line (Roland Rosenfeld)
|
||||
* Put options in cssh pod into alphabetical order
|
||||
- Add in bugtracker and homepage resources to Build.PL file
|
||||
- Bring new module App::ClusterSSH::Host into play for parsing host strings
|
||||
- Patch to override font used on command line (Roland Rosenfeld)
|
||||
- Put options in cssh pod into alphabetical order
|
||||
|
||||
2010-01-08 Duncan Ferguson <duncan_ferguson@user.sf.net> - v4.00_01
|
||||
4.00_01 2010-01-08 Duncan Ferguson <duncan_ferguson@user.sf.net>
|
||||
|
||||
* Remove GNU tools and switch to Perl module layout using Module::Build
|
||||
- Remove GNU tools and switch to Perl module layout using Module::Build
|
||||
|
||||
0000-00-00 Duncan Ferguson <duncan_ferguson@user.sf.net> - v3.29 - unreleased
|
||||
3.29 0000-00-00 Duncan Ferguson <duncan_ferguson@user.sf.net> (unreleased)
|
||||
|
||||
* Handle hostnames containing % properly (Debian bug 543368)
|
||||
- Handle hostnames containing % properly (Debian bug 543368)
|
||||
- Thanks to Tony Mancill for the patch
|
||||
|
||||
2009-12-19 Duncan Ferguson <duncan_ferguson@user.sf.net> - v3.28
|
||||
3.28 2009-12-19 Duncan Ferguson <duncan_ferguson@user.sf.net>
|
||||
|
||||
* Look for usernames when adding clusters
|
||||
- Look for usernames when adding clusters
|
||||
- Thanks to Kristian Lyngstol for the patch
|
||||
* Allow username@cluster to override all usernames in the cluster
|
||||
* Account for multiple host definitions within ssh configuration file
|
||||
- Allow username@cluster to override all usernames in the cluster
|
||||
- Account for multiple host definitions within ssh configuration file
|
||||
- Thanks to anonymous for the patch
|
||||
* Allow for long line continuation in config files with a backslash
|
||||
- Allow for long line continuation in config files with a backslash
|
||||
- Thanks to Mike Loseke for the patch
|
||||
* Improve binary search to
|
||||
- Improve binary search to
|
||||
- ignore directories of the same name, and
|
||||
- always search for the binary if it is not fully qualified
|
||||
- Thanks to Ian Marsh for the patch
|
||||
* Always use the given host name, not the resolved host name, when opening the ssh connection (Debian bug 533406)
|
||||
- Always use the given host name, not the resolved host name, when opening the ssh connection (Debian bug 533406)
|
||||
|
||||
2009-09-24 Duncan Ferguson <duncan_ferguson@user.sf.net> - v3.27
|
||||
3.27 2009-09-24 Duncan Ferguson <duncan_ferguson@user.sf.net>
|
||||
|
||||
* Add in list of clusters to 'Add Host' window
|
||||
- Add in list of clusters to 'Add Host' window
|
||||
- thanks for Stanislas Rouvelin for the idea
|
||||
* Fix bug where unresolvable host stopped program running
|
||||
- Fix bug where unresolvable host stopped program running
|
||||
- thanks to Sami Kerola
|
||||
* Add in config for auto-tearoff of send and host menus
|
||||
- Add in config for auto-tearoff of send and host menus
|
||||
- thanks to James Chernikov for the idea
|
||||
* Add in send menu xml definition file
|
||||
- Add in send menu xml definition file
|
||||
- thanks to James Chernikov for the idea
|
||||
|
||||
2009-06-02 Duncan Ferguson <duncan_ferguson@user.sf.net> - v3.26-1
|
||||
3.26_1 2009-06-02 Duncan Ferguson <duncan_ferguson@user.sf.net>
|
||||
|
||||
* Allow user to set a different ConnectTimeout and -o string (Tony Mancill)
|
||||
* Fix warning from 'mandb' (Tony Mancill)
|
||||
* Continue connecting to unresolvable hosts (debian bug 499935) (Tony Mancill)
|
||||
* Correct bug with unset default ports (Tony Mancill)
|
||||
* Rearrange pod documentation to remove extraenous comment (Tony Mancill)
|
||||
* Cope better with IPv6 addresses
|
||||
* Fix bug with passing arguments from command line to comms method binary
|
||||
* Rework defaultport code
|
||||
* Add new "-a 'command'" option for running a command in each terminal
|
||||
* Fix bug with some host lookups failing
|
||||
* Set window hints on terminals slightly differently to help with tiling
|
||||
* Reserve 5 pixels on top and left hand side of terminals for better tiling
|
||||
* Increase reserve of screen from bottom from 40 pixels to 60
|
||||
* Better notes in docs for screen/terminal reserving
|
||||
* Minor fixup to docs formatting
|
||||
* Correct pasting mechanism into control window
|
||||
* Allow use of long options (swap Getopt::Std to Getopt::Long)
|
||||
* Remove deprecated '-i' option
|
||||
* Deprecate -d and -D, replaced with --debug
|
||||
* Allow for configurable max number of hosts within hosts menu before
|
||||
- Allow user to set a different ConnectTimeout and -o string (Tony Mancill)
|
||||
- Fix warning from 'mandb' (Tony Mancill)
|
||||
- Continue connecting to unresolvable hosts (debian bug 499935) (Tony Mancill)
|
||||
- Correct bug with unset default ports (Tony Mancill)
|
||||
- Rearrange pod documentation to remove extraenous comment (Tony Mancill)
|
||||
- Cope better with IPv6 addresses
|
||||
- Fix bug with passing arguments from command line to comms method binary
|
||||
- Rework defaultport code
|
||||
- Add new "-a 'command'" option for running a command in each terminal
|
||||
- Fix bug with some host lookups failing
|
||||
- Set window hints on terminals slightly differently to help with tiling
|
||||
- Reserve 5 pixels on top and left hand side of terminals for better tiling
|
||||
- Increase reserve of screen from bottom from 40 pixels to 60
|
||||
- Better notes in docs for screen/terminal reserving
|
||||
- Minor fixup to docs formatting
|
||||
- Correct pasting mechanism into control window
|
||||
- Allow use of long options (swap Getopt::Std to Getopt::Long)
|
||||
- Remove deprecated '-i' option
|
||||
- Deprecate -d and -D, replaced with --debug
|
||||
- Allow for configurable max number of hosts within hosts menu before
|
||||
starting a new column - see .csshrc doc for "max_host_menu_items".
|
||||
This is until Tk allows for scrollable menus
|
||||
* Amend default key_addhost from 'Control-plus' to 'Control-Shift-plus'
|
||||
* Add in a 'default' cluster tag, used when no tags provided on command line
|
||||
* Fix Alt-n pasting in a resolved hostname instead of the connection hostname
|
||||
* Disabled unmapping code until such time as a better way of doing it exists
|
||||
- Amend default key_addhost from 'Control-plus' to 'Control-Shift-plus'
|
||||
- Add in a 'default' cluster tag, used when no tags provided on command line
|
||||
- Fix Alt-n pasting in a resolved hostname instead of the connection hostname
|
||||
- Disabled unmapping code until such time as a better way of doing it exists
|
||||
- this is due to virtual desktop change triggering a retile
|
||||
|
||||
2009-03-26 Duncan Ferguson <duncan_ferguson@user.sf.net> - v3.25-1
|
||||
3.25_1 2009-03-26 Duncan Ferguson <duncan_ferguson@user.sf.net>
|
||||
|
||||
* Add patch from David F. Skoll for adding colour to terminals
|
||||
* Apply fix from Bogdan Pintea for DNS failing to resolve IPs
|
||||
* Allow the configuration files to be symlinks (debian bug 518196)
|
||||
* Add an 'EXAMPLES' section to the cssh documentation
|
||||
* List options alphabetically in documentation
|
||||
* Apply patch from Gerfried Fuchs/Tony Mancill for ports on the command line
|
||||
- Add patch from David F. Skoll for adding colour to terminals
|
||||
- Apply fix from Bogdan Pintea for DNS failing to resolve IPs
|
||||
- Allow the configuration files to be symlinks (debian bug 518196)
|
||||
- Add an 'EXAMPLES' section to the cssh documentation
|
||||
- List options alphabetically in documentation
|
||||
- Apply patch from Gerfried Fuchs/Tony Mancill for ports on the command line
|
||||
|
||||
2008-11-14 Duncan Ferguson <duncan_ferguson@user.sf.net> - v3.24-1
|
||||
3.24_1 2008-11-14 Duncan Ferguson <duncan_ferguson@user.sf.net>
|
||||
|
||||
* Do not attempt to re-resolve IP addresses
|
||||
* Apply patch from Dan Wallis
|
||||
- Do not attempt to re-resolve IP addresses
|
||||
- Apply patch from Dan Wallis
|
||||
- Add '-C <file>' command to load in specific config file
|
||||
- Typo correct in pod
|
||||
- Cope with random/strange config files better
|
||||
* Correct some minor typos
|
||||
* Create the .csshrc file if it doesnt already exist and amend pod
|
||||
* Amend host menu items to be a little more descriptive
|
||||
* Remove 'Catpure Terminal' from Hosts menu as it doesnt do anything useful
|
||||
- Correct some minor typos
|
||||
- Create the .csshrc file if it doesnt already exist and amend pod
|
||||
- Amend host menu items to be a little more descriptive
|
||||
- Remove 'Catpure Terminal' from Hosts menu as it doesnt do anything useful
|
||||
|
||||
2008-01-23 Duncan Ferguson <duncan_ferguson@user.sf.net> - v3.23-1
|
||||
3.23_1 2008-01-23 Duncan Ferguson <duncan_ferguson@user.sf.net>
|
||||
|
||||
* Apply bugfix supplied by Jima
|
||||
- Apply bugfix supplied by Jima
|
||||
- Ensure loading of hosts from user ssh config file is case insensitive
|
||||
|
||||
2008-01-23 Duncan Ferguson <duncan_ferguson@user.sf.net> - v3.22-1
|
||||
3.22_1 2008-01-23 Duncan Ferguson <duncan_ferguson@user.sf.net>
|
||||
|
||||
* Update X resources class to allow use of terms other than XTerm
|
||||
* Apply patch from Harald Weidner to stop error messages in Debian Etch
|
||||
* Add in key shortcut (alt-h) to toggle history window
|
||||
* Tidy up pod a little to highlight notes better
|
||||
* Check terminal_font config for quotes and remove
|
||||
* Enable use of "configure --sysconfdir=", defaults to /etc
|
||||
* Revise host checking algorithm to take ssh_config files into account
|
||||
* Revise username check used as part of host id to accept more chars
|
||||
* Correct year value for previous two entries from 2008 to 2007
|
||||
- Update X resources class to allow use of terms other than XTerm
|
||||
- Apply patch from Harald Weidner to stop error messages in Debian Etch
|
||||
- Add in key shortcut (alt-h) to toggle history window
|
||||
- Tidy up pod a little to highlight notes better
|
||||
- Check terminal_font config for quotes and remove
|
||||
- Enable use of "configure --sysconfdir=", defaults to /etc
|
||||
- Revise host checking algorithm to take ssh_config files into account
|
||||
- Revise username check used as part of host id to accept more chars
|
||||
- Correct year value for previous two entries from 2008 to 2007
|
||||
|
||||
2007-11-28 Duncan Ferguson <duncan_ferguson@user.sf.net> - v3.21-1
|
||||
3.21_1 2007-11-28 Duncan Ferguson <duncan_ferguson@user.sf.net>
|
||||
|
||||
* Implement a basic history window in the console (option -s)
|
||||
* Fixed bug whereby username@ wasn't being used correctly
|
||||
- Implement a basic history window in the console (option -s)
|
||||
- Fixed bug whereby username@ wasn't being used correctly
|
||||
|
||||
2007-11-26 Duncan Ferguson <duncan_ferguson@user.sf.net> - v3.20-1
|
||||
3.20_1 2007-11-26 Duncan Ferguson <duncan_ferguson@user.sf.net>
|
||||
|
||||
* Move source repository from CVS to SVN on sourceforge
|
||||
* Remove last digit of version number since not required with SVN
|
||||
* Add in host menu option to close inactive windows
|
||||
* Apply bugfixes suppled by Tony Mancill
|
||||
- Move source repository from CVS to SVN on sourceforge
|
||||
- Remove last digit of version number since not required with SVN
|
||||
- Add in host menu option to close inactive windows
|
||||
- Apply bugfixes suppled by Tony Mancill
|
||||
- reset xrm switch in terminal_args
|
||||
- prevent warning messages being printed when keysyms arent found
|
||||
- fixes for fvwm
|
||||
- chekc for child process before sending kill
|
||||
* Slight rewording of man page
|
||||
* Add in option to use telnet as comms command (use 'ctel' to invoke script)
|
||||
* Run through perltidy -b -i=2
|
||||
* Appy patches from Klaus Ethgen
|
||||
- Slight rewording of man page
|
||||
- Add in option to use telnet as comms command (use 'ctel' to invoke script)
|
||||
- Run through perltidy -b -i=2
|
||||
- Appy patches from Klaus Ethgen
|
||||
- Client dies when cannot write to pipe
|
||||
- Sleeping and flushing in window manager to allow time to draw windows
|
||||
- Fix pipe reading to not use undefined values
|
||||
* Apply patches from Nicolas Simonds
|
||||
- Apply patches from Nicolas Simonds
|
||||
- allow colons in hostnames
|
||||
- allow -o option as per man page
|
||||
* Apply patch from Peter Palfrader
|
||||
- Apply patch from Peter Palfrader
|
||||
- improvement to finding binaries
|
||||
* Allow font to be specified on the command line
|
||||
* Check for errors around key data gathering
|
||||
* Add in 'extra_cluster_file' to csshrc
|
||||
- Allow font to be specified on the command line
|
||||
- Check for errors around key data gathering
|
||||
- Add in 'extra_cluster_file' to csshrc
|
||||
|
||||
2006-07-24 Duncan Ferguson <duncan_ferguson@user.sf.net> - v3.19.1-1
|
||||
3.19.1_1 2006-07-24 Duncan Ferguson <duncan_ferguson@user.sf.net>
|
||||
|
||||
- Below is an abridged version of changes - see CVS for more information
|
||||
* Check for failure to connect to X session
|
||||
* Totally rework character mapping and events to cope with non-QWERTY keyboards
|
||||
* Rework pasting code to cope with non-QWERTY charatcters
|
||||
* Manpage/help doc updates and corrections
|
||||
* Check for missing definitions for cluster tags in .csshrc
|
||||
* Run through perltidy -b -i=2
|
||||
* Apply patch to add in optional port information from D. Dumont
|
||||
* Amend hotkey code to not pick up <ctrl>-<alt> as default clientname shortcut
|
||||
* Alter repeat function to improve efficiency
|
||||
* Rework retiling code
|
||||
* Add "-e <host>" to evaluate terminal and communcation methods
|
||||
* Add in toggle option on hosts menu
|
||||
* Fix check in find_binary to ensure one is actually found
|
||||
* Search $PATH and other standard places for binaries incase $PATH is incomplete
|
||||
* Amend code to allow getting help when no X display available
|
||||
* Allow override of both key and mouse paste key sequences
|
||||
* Added icons and desktop file
|
||||
* Amended clusterssh.spec to cope with icons and desktop file
|
||||
* Improve cluster file import efficiency as was taking faaar too long previously
|
||||
* Fixed bug whereby when pid's of the xterm changes records were not updated
|
||||
* Do not die when pipe open fails, but continue as others may be connected
|
||||
* Remove code that breaks the minimize/maximise stuff;
|
||||
* Catch X button presses on title bar to close all windows correctly
|
||||
* Delay map event capture at program start to avoid infinite loop
|
||||
* Fix execvp error on Solaris 10
|
||||
- Check for failure to connect to X session
|
||||
- Totally rework character mapping and events to cope with non-QWERTY keyboards
|
||||
- Rework pasting code to cope with non-QWERTY charatcters
|
||||
- Manpage/help doc updates and corrections
|
||||
- Check for missing definitions for cluster tags in .csshrc
|
||||
- Run through perltidy -b -i=2
|
||||
- Apply patch to add in optional port information from D. Dumont
|
||||
- Amend hotkey code to not pick up <ctrl>-<alt> as default clientname shortcut
|
||||
- Alter repeat function to improve efficiency
|
||||
- Rework retiling code
|
||||
- Add "-e <host>" to evaluate terminal and communcation methods
|
||||
- Add in toggle option on hosts menu
|
||||
- Fix check in find_binary to ensure one is actually found
|
||||
- Search $PATH and other standard places for binaries incase $PATH is incomplete
|
||||
- Amend code to allow getting help when no X display available
|
||||
- Allow override of both key and mouse paste key sequences
|
||||
- Added icons and desktop file
|
||||
- Amended clusterssh.spec to cope with icons and desktop file
|
||||
- Improve cluster file import efficiency as was taking faaar too long previously
|
||||
- Fixed bug whereby when pid's of the xterm changes records were not updated
|
||||
- Do not die when pipe open fails, but continue as others may be connected
|
||||
- Remove code that breaks the minimize/maximise stuff;
|
||||
- Catch X button presses on title bar to close all windows correctly
|
||||
- Delay map event capture at program start to avoid infinite loop
|
||||
- Fix execvp error on Solaris 10
|
||||
|
||||
2005-11-28 Duncan Ferguson <duncan_ferguson@user.sf.net> - v3.18.1-1
|
||||
3.18.1_1 2005-11-28 Duncan Ferguson <duncan_ferguson@user.sf.net>
|
||||
|
||||
* Correct mask value for backtick (grave) character
|
||||
* Add more logging for debug mode
|
||||
* Amend indentation
|
||||
* Rerun through perltidy
|
||||
* Improve cluster file import efficiency as was taking faaar too long previously
|
||||
* Fixed bug whereby when pid's of the xterm changes records were not updated
|
||||
* Do not die when pipe open fails, but continue as others may be connected
|
||||
* Remove code that breaks the minimize/maximise stuff;
|
||||
* Catch X button presses on title bar to close all windows correctly
|
||||
* Delay map event capture at program start to avoid infinite loop
|
||||
* Fix execvp error on Solaris 10
|
||||
* Update to man pages
|
||||
- Correct mask value for backtick (grave) character
|
||||
- Add more logging for debug mode
|
||||
- Amend indentation
|
||||
- Rerun through perltidy
|
||||
- Improve cluster file import efficiency as was taking faaar too long previously
|
||||
- Fixed bug whereby when pid's of the xterm changes records were not updated
|
||||
- Do not die when pipe open fails, but continue as others may be connected
|
||||
- Remove code that breaks the minimize/maximise stuff;
|
||||
- Catch X button presses on title bar to close all windows correctly
|
||||
- Delay map event capture at program start to avoid infinite loop
|
||||
- Fix execvp error on Solaris 10
|
||||
- Update to man pages
|
||||
|
||||
2005-06-24 Duncan Ferguson <duncan_ferguson@user.sf.net> - v3.17.1
|
||||
3.17.1 2005-06-24 Duncan Ferguson <duncan_ferguson@user.sf.net>
|
||||
|
||||
* Allow _'s in paste text correctly
|
||||
* Bugfix minimise/maximise again
|
||||
* Run through "perltidy -i=4 -ce"
|
||||
* Unmap all windows in one go instead of one at a time when retiling
|
||||
* Add + doc 'console_position'
|
||||
* Maintain user position of console between maps (i.e. tell window manager
|
||||
- Allow _'s in paste text correctly
|
||||
- Bugfix minimise/maximise again
|
||||
- Run through "perltidy -i=4 -ce"
|
||||
- Unmap all windows in one go instead of one at a time when retiling
|
||||
- Add + doc 'console_position'
|
||||
- Maintain user position of console between maps (i.e. tell window manager
|
||||
not to move it)
|
||||
* Note that ssh options are for OpenSSH not for any other ssh version
|
||||
- Note that ssh options are for OpenSSH not for any other ssh version
|
||||
|
||||
2005-06-13 Duncan Ferguson <duncan_ferguson@user.sf.net> - v3.16.1
|
||||
3.16.1 2005-06-13 Duncan Ferguson <duncan_ferguson@user.sf.net>
|
||||
|
||||
* Allow ignoring of unresolved hosts (i.e. if hostname aliased in
|
||||
- Allow ignoring of unresolved hosts (i.e. if hostname aliased in
|
||||
ssh config file)
|
||||
|
||||
2005-06-09 Duncan Ferguson <duncan_ferguson@user.sf.net> - v3.15.1
|
||||
3.15.1 2005-06-09 Duncan Ferguson <duncan_ferguson@user.sf.net>
|
||||
|
||||
* Add and document "-c <clusterfile>"
|
||||
* Add and document "-l <username>"
|
||||
* Add and document "-o <options>"
|
||||
* Document "-t <title>"
|
||||
* Set controlled terminals to have user set size & position (WM_SIZE_HINTS)
|
||||
* Speed up initial terminal openings
|
||||
* Remove all key bindings from drop down menus (conflicts with emacs and
|
||||
- Add and document "-c <clusterfile>"
|
||||
- Add and document "-l <username>"
|
||||
- Add and document "-o <options>"
|
||||
- Document "-t <title>"
|
||||
- Set controlled terminals to have user set size & position (WM_SIZE_HINTS)
|
||||
- Speed up initial terminal openings
|
||||
- Remove all key bindings from drop down menus (conflicts with emacs and
|
||||
can all be done by other hotkeys anyhow)
|
||||
* Allow individual hotkeys to be disabled, instead of all-or-nothing
|
||||
* Updates to POD
|
||||
* Update retile code to avoid flickering windows (& also fix cygwin bug)
|
||||
* Rename -t to -T to match previous series option
|
||||
* Added in -t to modify cmd line args for terminals
|
||||
- Allow individual hotkeys to be disabled, instead of all-or-nothing
|
||||
- Updates to POD
|
||||
- Update retile code to avoid flickering windows (& also fix cygwin bug)
|
||||
- Rename -t to -T to match previous series option
|
||||
- Added in -t to modify cmd line args for terminals
|
||||
|
||||
2005-06-04 Duncan Ferguson <duncan_ferguson@user.sf.net> - v3.14.1
|
||||
3.14.1 2005-06-04 Duncan Ferguson <duncan_ferguson@user.sf.net>
|
||||
|
||||
* first cut at terminal opening speed up
|
||||
- first cut at terminal opening speed up
|
||||
|
||||
2005-05-20 Duncan Ferguson <duncan_ferguson@user.sf.net> - v3.13.1
|
||||
3.13.1 2005-05-20 Duncan Ferguson <duncan_ferguson@user.sf.net>
|
||||
|
||||
* Bugfix for whitespace in config files (missing a char from regexp)
|
||||
* Allow for minimising/maximising all windows when done on console
|
||||
- Bugfix for whitespace in config files (missing a char from regexp)
|
||||
- Allow for minimising/maximising all windows when done on console
|
||||
|
||||
2005-05-19 Duncan Ferguson <duncan_ferguson@user.sf.net> - v3.12.1
|
||||
3.12.1 2005-05-19 Duncan Ferguson <duncan_ferguson@user.sf.net>
|
||||
|
||||
* Bugfix for shifted non-alphanumeric keyboard chars not being pasted correctly
|
||||
* Marked version number with 3rd digit to signify beta releases
|
||||
- Bugfix for shifted non-alphanumeric keyboard chars not being pasted correctly
|
||||
- Marked version number with 3rd digit to signify beta releases
|
||||
|
||||
2005-05-18 Duncan Ferguson <duncan_ferguson@user.sf.net> - v3.11
|
||||
3.11 2005-05-18 Duncan Ferguson <duncan_ferguson@user.sf.net>
|
||||
|
||||
* Remove trailing whitespace from config file lines
|
||||
* Prevent paste events being sent to non-active clients
|
||||
* Allow paste events to send capitalised letters
|
||||
- Remove trailing whitespace from config file lines
|
||||
- Prevent paste events being sent to non-active clients
|
||||
- Allow paste events to send capitalised letters
|
||||
|
||||
2005-05-17 Duncan Ferguson <duncan_ferguson@user.sf.net> - v3.10
|
||||
3.10 2005-05-17 Duncan Ferguson <duncan_ferguson@user.sf.net>
|
||||
|
||||
* fix for moving atom numbers in font info
|
||||
- fix for moving atom numbers in font info
|
||||
|
||||
2005-05-11 Duncan Ferguson <duncan_ferguson@user.sf.net> - v3.9
|
||||
3.9 2005-05-11 Duncan Ferguson <duncan_ferguson@user.sf.net>
|
||||
|
||||
* Allow multiple hosts or tags in the "Add Host" text widget
|
||||
* Retile all windows (if set) after adding a host
|
||||
* Do not automatically send a return after hostname (Alt-n)
|
||||
* Fix bug with sending read hostname instead of internal unique host
|
||||
- Allow multiple hosts or tags in the "Add Host" text widget
|
||||
- Retile all windows (if set) after adding a host
|
||||
- Do not automatically send a return after hostname (Alt-n)
|
||||
- Fix bug with sending read hostname instead of internal unique host
|
||||
name (Alt-n)
|
||||
* Fix bug whereby cannot start cssh without any hosts on cmd-line
|
||||
* Fix bug where client name was sent to inactive clients
|
||||
* Fix bug whereby 0's in sent text were ignored
|
||||
- Fix bug whereby cannot start cssh without any hosts on cmd-line
|
||||
- Fix bug where client name was sent to inactive clients
|
||||
- Fix bug whereby 0's in sent text were ignored
|
||||
|
||||
2005-05-09 Duncan Ferguson <duncan_ferguson@user.sf.net> - v3.8
|
||||
3.8 2005-05-09 Duncan Ferguson <duncan_ferguson@user.sf.net>
|
||||
|
||||
* Remove the need for xlsfonts (perform function by X window calls instead)
|
||||
* Debug level output changes
|
||||
* Ensure windows are overlapping in the right places, instead of any order
|
||||
* Create config section on window decorations (i.e. title & scroll bars)
|
||||
- Remove the need for xlsfonts (perform function by X window calls instead)
|
||||
- Debug level output changes
|
||||
- Ensure windows are overlapping in the right places, instead of any order
|
||||
- Create config section on window decorations (i.e. title & scroll bars)
|
||||
|
||||
2005-05-05 Duncan Ferguson <duncan_ferguson@user.sf.net> - v3.7
|
||||
3.7 2005-05-05 Duncan Ferguson <duncan_ferguson@user.sf.net>
|
||||
|
||||
* Found ConfigureWindow instead of ResizeMoveWindow
|
||||
- Found ConfigureWindow instead of ResizeMoveWindow
|
||||
|
||||
2005-05-05 Duncan Ferguson <duncan_ferguson@user.sf.net> - v3.6
|
||||
3.6 2005-05-05 Duncan Ferguson <duncan_ferguson@user.sf.net>
|
||||
|
||||
* Lots of work on window tiling - to fall at last hurdle (No XResizeMoveWindow)
|
||||
* Documentation updates
|
||||
* Allow -u ouput when binaries havnt been found
|
||||
* Start coding for capturing an existing terminal window
|
||||
* Rebuild hosts menu when all hosts checked, not when each host checked
|
||||
* Change debug message output level of keysyms
|
||||
* Cater for config of no tiling, but allow to retile in console window anyhow
|
||||
- Lots of work on window tiling - to fall at last hurdle (No XResizeMoveWindow)
|
||||
- Documentation updates
|
||||
- Allow -u ouput when binaries havnt been found
|
||||
- Start coding for capturing an existing terminal window
|
||||
- Rebuild hosts menu when all hosts checked, not when each host checked
|
||||
- Change debug message output level of keysyms
|
||||
- Cater for config of no tiling, but allow to retile in console window anyhow
|
||||
|
||||
2005-05-03 Duncan Ferguson <duncan_ferguson@user.sf.net> - v3.5
|
||||
3.5 2005-05-03 Duncan Ferguson <duncan_ferguson@user.sf.net>
|
||||
|
||||
* Remove some old (commented out) code
|
||||
* Remove some (unnecessary) debug code
|
||||
* Start coding for window tiling
|
||||
* Modify find_binary function to make it more portable
|
||||
* Output internal vars in "-u -d"
|
||||
* Small mods to docs to take account of all of the above
|
||||
- Remove some old (commented out) code
|
||||
- Remove some (unnecessary) debug code
|
||||
- Start coding for window tiling
|
||||
- Modify find_binary function to make it more portable
|
||||
- Output internal vars in "-u -d"
|
||||
- Small mods to docs to take account of all of the above
|
||||
|
||||
2005-04-26 Duncan Ferguson <duncan_ferguson@user.sf.net> - v3.4
|
||||
3.4 2005-04-26 Duncan Ferguson <duncan_ferguson@user.sf.net>
|
||||
|
||||
* Changed order of "use POSIX" to put :sys_wait_h first to avoid chance of
|
||||
- Changed order of "use POSIX" to put :sys_wait_h first to avoid chance of
|
||||
hitting known issue
|
||||
* Allow for running from cvs dir in config{comms}
|
||||
* Add "ConnectTimeout=10" to default ssh options
|
||||
* Add further debug info
|
||||
* Add check to ensure hostname can be resolved before attempting connection
|
||||
* Modigy zombie reaping to prevent hand on unconnected cx term closing
|
||||
* Add "autoquit" feature to close ClusterSSH after last client window closes
|
||||
* Also produce man page and include as part of install
|
||||
- Allow for running from cvs dir in config{comms}
|
||||
- Add "ConnectTimeout=10" to default ssh options
|
||||
- Add further debug info
|
||||
- Add check to ensure hostname can be resolved before attempting connection
|
||||
- Modigy zombie reaping to prevent hand on unconnected cx term closing
|
||||
- Add "autoquit" feature to close ClusterSSH after last client window closes
|
||||
- Also produce man page and include as part of install
|
||||
|
||||
2005-04-10 Duncan Ferguson <duncan_ferguson@user.sf.net> - v3.3
|
||||
3.3 2005-04-10 Duncan Ferguson <duncan_ferguson@user.sf.net>
|
||||
|
||||
* src/cssh.pl: Rewritten from scratch
|
||||
* Set up to use Gnu Autotools
|
||||
|
||||
$Id$
|
||||
- src/cssh.pl: Rewritten from scratch
|
||||
- Set up to use Gnu Autotools
|
||||
|
|
46
MANIFEST
46
MANIFEST
|
@ -1,46 +0,0 @@
|
|||
AUTHORS
|
||||
bin/ccon
|
||||
bin/crsh
|
||||
bin/cscp
|
||||
bin/cssh
|
||||
bin/ctel
|
||||
Build.PL
|
||||
Changes
|
||||
lib/App/ClusterSSH.pm
|
||||
lib/App/ClusterSSH/Base.pm
|
||||
lib/App/ClusterSSH/Cluster.pm
|
||||
lib/App/ClusterSSH/Config.pm
|
||||
lib/App/ClusterSSH/Helper.pm
|
||||
lib/App/ClusterSSH/Host.pm
|
||||
lib/App/ClusterSSH/L10N.pm
|
||||
lib/App/ClusterSSH/L10N/en.pm
|
||||
Makefile.PL
|
||||
MANIFEST
|
||||
MANIFEST.SKIP
|
||||
META.json
|
||||
META.yml
|
||||
README
|
||||
t/00-load.t
|
||||
t/01l10n.t
|
||||
t/02base.t
|
||||
t/10host.t
|
||||
t/10host_ssh_config
|
||||
t/15config.t
|
||||
t/15config.t.file1
|
||||
t/15config.t.file2
|
||||
t/15config.t.file3
|
||||
t/20helper.t
|
||||
t/30cluster.cannot_read
|
||||
t/30cluster.file1
|
||||
t/30cluster.file2
|
||||
t/30cluster.file3
|
||||
t/30cluster.t
|
||||
t/30cluster.tag1
|
||||
t/80clusterssh.t
|
||||
t/boilerplate.t
|
||||
t/external_cluster_command
|
||||
t/manifest.t
|
||||
t/pod-coverage.t
|
||||
t/pod.t
|
||||
THANKS
|
||||
TODO
|
|
@ -1,16 +0,0 @@
|
|||
^App-ClusterSSH-.*
|
||||
^blib/
|
||||
^_build/
|
||||
^Build$
|
||||
^cover_db/
|
||||
^.git/
|
||||
^.gitignore
|
||||
^Makefile$
|
||||
^Makefile.old$
|
||||
^MANIFEST\.bak$
|
||||
MYMETA.json
|
||||
MYMETA.yml
|
||||
pm_to_blib
|
||||
.*\.swp$
|
||||
^TOAD$
|
||||
^WIP_TASKS$
|
94
META.json
94
META.json
|
@ -1,94 +0,0 @@
|
|||
{
|
||||
"abstract" : "A container for functions of the ClusterSSH programs",
|
||||
"author" : [
|
||||
"Duncan Ferguson <duncan_j_ferguson@yahoo.co.uk>"
|
||||
],
|
||||
"dynamic_config" : 1,
|
||||
"generated_by" : "Module::Build version 0.4003, CPAN::Meta::Converter version 2.120921",
|
||||
"license" : [
|
||||
"perl_5"
|
||||
],
|
||||
"meta-spec" : {
|
||||
"url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec",
|
||||
"version" : "2"
|
||||
},
|
||||
"name" : "App-ClusterSSH",
|
||||
"prereqs" : {
|
||||
"build" : {
|
||||
"requires" : {
|
||||
"File::Temp" : "0",
|
||||
"File::Which" : "0",
|
||||
"Readonly" : "0",
|
||||
"Test::Differences" : "0",
|
||||
"Test::DistManifest" : "0",
|
||||
"Test::Pod" : "0",
|
||||
"Test::Pod::Coverage" : "0",
|
||||
"Test::Trap" : "0"
|
||||
}
|
||||
},
|
||||
"configure" : {
|
||||
"requires" : {
|
||||
"Module::Build" : "0"
|
||||
}
|
||||
},
|
||||
"runtime" : {
|
||||
"requires" : {
|
||||
"Exception::Class" : "1.31",
|
||||
"Locale::Maketext" : "0",
|
||||
"Tk" : "800.022",
|
||||
"Try::Tiny" : "0",
|
||||
"X11::Protocol" : "0.56",
|
||||
"version" : "0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"provides" : {
|
||||
"App::ClusterSSH" : {
|
||||
"file" : "lib/App/ClusterSSH.pm",
|
||||
"version" : "4.02_02"
|
||||
},
|
||||
"App::ClusterSSH::Base" : {
|
||||
"file" : "lib/App/ClusterSSH/Base.pm",
|
||||
"version" : "0.02"
|
||||
},
|
||||
"App::ClusterSSH::Cluster" : {
|
||||
"file" : "lib/App/ClusterSSH/Cluster.pm",
|
||||
"version" : "0.01"
|
||||
},
|
||||
"App::ClusterSSH::Config" : {
|
||||
"file" : "lib/App/ClusterSSH/Config.pm",
|
||||
"version" : "0.02"
|
||||
},
|
||||
"App::ClusterSSH::Helper" : {
|
||||
"file" : "lib/App/ClusterSSH/Helper.pm",
|
||||
"version" : "0.02"
|
||||
},
|
||||
"App::ClusterSSH::Host" : {
|
||||
"file" : "lib/App/ClusterSSH/Host.pm",
|
||||
"version" : "0.03"
|
||||
},
|
||||
"App::ClusterSSH::L10N" : {
|
||||
"file" : "lib/App/ClusterSSH/L10N.pm",
|
||||
"version" : 0
|
||||
},
|
||||
"App::ClusterSSH::L10N::en" : {
|
||||
"file" : "lib/App/ClusterSSH/L10N/en.pm",
|
||||
"version" : 0
|
||||
}
|
||||
},
|
||||
"release_status" : "testing",
|
||||
"resources" : {
|
||||
"bugtracker" : {
|
||||
"web" : "http://sourceforge.net/tracker/?group_id=89139"
|
||||
},
|
||||
"homepage" : "http://clusterssh.sourceforge.net/",
|
||||
"license" : [
|
||||
"http://dev.perl.org/licenses/"
|
||||
],
|
||||
"x_Repository" : [
|
||||
"http://clusterssh.git.sourceforge.net/",
|
||||
"http://github.com/duncs/clusterssh"
|
||||
]
|
||||
},
|
||||
"version" : "4.02_02"
|
||||
}
|
62
META.yml
62
META.yml
|
@ -1,62 +0,0 @@
|
|||
---
|
||||
abstract: 'A container for functions of the ClusterSSH programs'
|
||||
author:
|
||||
- 'Duncan Ferguson <duncan_j_ferguson@yahoo.co.uk>'
|
||||
build_requires:
|
||||
File::Temp: 0
|
||||
File::Which: 0
|
||||
Readonly: 0
|
||||
Test::Differences: 0
|
||||
Test::DistManifest: 0
|
||||
Test::Pod: 0
|
||||
Test::Pod::Coverage: 0
|
||||
Test::Trap: 0
|
||||
configure_requires:
|
||||
Module::Build: 0
|
||||
dynamic_config: 1
|
||||
generated_by: 'Module::Build version 0.4003, CPAN::Meta::Converter version 2.120921'
|
||||
license: perl
|
||||
meta-spec:
|
||||
url: http://module-build.sourceforge.net/META-spec-v1.4.html
|
||||
version: 1.4
|
||||
name: App-ClusterSSH
|
||||
provides:
|
||||
App::ClusterSSH:
|
||||
file: lib/App/ClusterSSH.pm
|
||||
version: 4.02_02
|
||||
App::ClusterSSH::Base:
|
||||
file: lib/App/ClusterSSH/Base.pm
|
||||
version: 0.02
|
||||
App::ClusterSSH::Cluster:
|
||||
file: lib/App/ClusterSSH/Cluster.pm
|
||||
version: 0.01
|
||||
App::ClusterSSH::Config:
|
||||
file: lib/App/ClusterSSH/Config.pm
|
||||
version: 0.02
|
||||
App::ClusterSSH::Helper:
|
||||
file: lib/App/ClusterSSH/Helper.pm
|
||||
version: 0.02
|
||||
App::ClusterSSH::Host:
|
||||
file: lib/App/ClusterSSH/Host.pm
|
||||
version: 0.03
|
||||
App::ClusterSSH::L10N:
|
||||
file: lib/App/ClusterSSH/L10N.pm
|
||||
version: 0
|
||||
App::ClusterSSH::L10N::en:
|
||||
file: lib/App/ClusterSSH/L10N/en.pm
|
||||
version: 0
|
||||
requires:
|
||||
Exception::Class: 1.31
|
||||
Locale::Maketext: 0
|
||||
Tk: 800.022
|
||||
Try::Tiny: 0
|
||||
X11::Protocol: 0.56
|
||||
version: 0
|
||||
resources:
|
||||
bugtracker: http://sourceforge.net/tracker/?group_id=89139
|
||||
homepage: http://clusterssh.sourceforge.net/
|
||||
license: http://dev.perl.org/licenses/
|
||||
x_Repository:
|
||||
- http://clusterssh.git.sourceforge.net/
|
||||
- http://github.com/duncs/clusterssh
|
||||
version: 4.02_02
|
33
Makefile.PL
33
Makefile.PL
|
@ -1,33 +0,0 @@
|
|||
# Note: this file was auto-generated by Module::Build::Compat version 0.4003
|
||||
use ExtUtils::MakeMaker;
|
||||
WriteMakefile
|
||||
(
|
||||
'NAME' => 'App::ClusterSSH',
|
||||
'VERSION_FROM' => 'lib/App/ClusterSSH.pm',
|
||||
'PREREQ_PM' => {
|
||||
'Exception::Class' => '1.31',
|
||||
'File::Temp' => 0,
|
||||
'File::Which' => 0,
|
||||
'Locale::Maketext' => 0,
|
||||
'Readonly' => 0,
|
||||
'Test::Differences' => 0,
|
||||
'Test::DistManifest' => 0,
|
||||
'Test::Pod' => 0,
|
||||
'Test::Pod::Coverage' => 0,
|
||||
'Test::Trap' => 0,
|
||||
'Tk' => '800.022',
|
||||
'Try::Tiny' => 0,
|
||||
'X11::Protocol' => '0.56',
|
||||
'version' => '0'
|
||||
},
|
||||
'INSTALLDIRS' => 'site',
|
||||
'EXE_FILES' => [
|
||||
'bin/ccon',
|
||||
'bin/crsh',
|
||||
'bin/cscp',
|
||||
'bin/cssh',
|
||||
'bin/ctel'
|
||||
],
|
||||
'PL_FILES' => {}
|
||||
)
|
||||
;
|
787
README
787
README
|
@ -1,67 +1,768 @@
|
|||
App-ClusterSSH
|
||||
NAME
|
||||
cssh - Cluster administration tool
|
||||
|
||||
The is the Perl application bundle for ClusterSSH (a.k.a cssh), formally
|
||||
a GNU tools based project.
|
||||
VERSION
|
||||
This documentation is for version: 4.18
|
||||
|
||||
ClusterSSH is a tool for making the same change on multiple servers at
|
||||
the same time. The 'cssh' command opens an administration console and
|
||||
an xterm to all specified hosts. Any text typed into the administration
|
||||
console is replicated to all windows. All windows may also be typed into
|
||||
directly.
|
||||
SYNOPSIS
|
||||
cssh [-a '<command>'] [-K <seconds>] [-q] [-c '<filename>'] [-x <cols>]
|
||||
[-C '<filename>'] [--debug [[...] || <INTEGER>]] [-d] [-e
|
||||
'<[user@]<host>[:port]>'] [--fillscreen] [-f '<font>'] [-h] [-L '[tag]']
|
||||
[-H] [-o '<STRING>'] [-p <port>] [-Q] [-y <rows>] [-s] [-r '<filename>']
|
||||
[-t '<STRING>'] [-g] [-T '<title>'] [-u] [-?] [-A] [-l '<username>']
|
||||
[-v]
|
||||
|
||||
This tool is intended for (but not limited to) cluster administration
|
||||
where the same configuration or commands must be run on each node
|
||||
within the cluster. Performing these commands all at once via this
|
||||
tool ensures all nodes are kept in sync.
|
||||
RELATED
|
||||
Also see the individual man pages for each of these utilities
|
||||
|
||||
For more information, go to http://clusterssh.sourceforge.net
|
||||
ccon - Use 'console' as the communication method
|
||||
crsh - Use 'rsh' as the communication method
|
||||
csftp - Use 'sftp' as the communication method
|
||||
ctel - Use 'telnet' as the communication method
|
||||
|
||||
INSTALLATION
|
||||
DESCRIPTION
|
||||
The command opens an administration console and an xterm to all
|
||||
specified hosts. Any text typed into the administration console is
|
||||
replicated to all windows. All windows may also be typed into directly.
|
||||
|
||||
To install this module, run the following commands:
|
||||
This tool is intended for (but not limited to) cluster administration
|
||||
where the same configuration or commands must be run on each node within
|
||||
the cluster. Performing these commands all at once via this tool ensures
|
||||
all nodes are kept in sync.
|
||||
|
||||
perl Build.PL
|
||||
./Build
|
||||
./Build test
|
||||
./Build install
|
||||
Connections are opened using ssh which must be correctly installed and
|
||||
configured.
|
||||
|
||||
SUPPORT AND DOCUMENTATION
|
||||
Extra caution should be taken when editing files as lines may not
|
||||
necessarily be in the same order; assuming line 5 is the same across all
|
||||
servers and modifying that is dangerous. It's better to search for the
|
||||
specific line to be changed and double-check all terminals are as
|
||||
expected before changes are committed.
|
||||
|
||||
After installing, you can find documentation for this module with the
|
||||
perldoc command.
|
||||
Further Notes
|
||||
Please also see "KNOWN BUGS".
|
||||
|
||||
perldoc cssh
|
||||
* The dotted line on any sub-menu is a tear-off, i.e. click on it and
|
||||
the sub-menu is turned into its own window.
|
||||
|
||||
or (if your MANPATH is set up appropriately)
|
||||
* Unchecking a hostname on the Hosts sub-menu will unplug the host
|
||||
from the cluster control window, so any text typed into the console
|
||||
is not sent to that host. Re-selecting it will plug it back in.
|
||||
|
||||
man cssh
|
||||
* If your window manager menu bars are obscured by terminal windows
|
||||
see the "screen_reserve_XXXXX" options in the
|
||||
$HOME/.clusterssh/config file (see "FILES").
|
||||
|
||||
You can also look for information at:
|
||||
* If the terminals overlap too much see the "terminal_reserve_XXXXX"
|
||||
options in the $HOME/.clusterssh/config file (see "FILES").
|
||||
|
||||
Web site and SourceForge project page
|
||||
http://clusterssh.sourceforge.net
|
||||
http://sourceforge.net/projects/clusterssh/
|
||||
* When using ClusterSSH on a large number of systems to connect to a
|
||||
single system using an SSH utility (e.g. you issue a command to to
|
||||
copy a file using scp from the remote computers to a single host)
|
||||
and when these connections require authentication (i.e. you are
|
||||
going to authenticate with a password), the sshd daemon at that
|
||||
location may refuse connections after the number "MaxStartups" limit
|
||||
in sshd_config is exceeded. (If this value is not set, it defaults
|
||||
to 10). This is expected behavior; sshd uses this mechanism to
|
||||
prevent DoS attacks from unauthenticated sources. Please tune
|
||||
sshd_config and reload the SSH daemon, or consider using the
|
||||
~/.ssh/authorized_keys mechanism for authentication if you encounter
|
||||
this problem.
|
||||
|
||||
Project support area
|
||||
https://sourceforge.net/projects/clusterssh/support
|
||||
* If client windows fail to open, try running:
|
||||
|
||||
AnnoCPAN, Annotated CPAN documentation
|
||||
http://annocpan.org/dist/App-ClusterSSH
|
||||
"cssh -e {single host name}"
|
||||
|
||||
CPAN Ratings
|
||||
http://cpanratings.perl.org/d/App-ClusterSSH
|
||||
This will test the mechanisms used to open windows to hosts. This
|
||||
could be due to either the "-xrm" terminal option which enables
|
||||
"AllowSendEvents" (some terminals do not require this option, other
|
||||
terminals have another method for enabling it - see your terminal
|
||||
documentation) or the configuration of "ssh".
|
||||
|
||||
Search CPAN
|
||||
http://search.cpan.org/dist/App-ClusterSSH/
|
||||
OPTIONS
|
||||
Some of these options may also be defined within the configuration file.
|
||||
Default options are shown as appropriate.
|
||||
|
||||
--action '<command>', -a '<command>'
|
||||
Run the command in each session, e.g. "-a 'vi /etc/hosts'" to drop
|
||||
straight into a vi session.
|
||||
|
||||
COPYRIGHT AND LICENCE
|
||||
--autoclose <seconds>, -K <seconds>
|
||||
Number of seconds to wait before closing finished terminal windows.
|
||||
|
||||
Copyright (C) 1999-2010 Duncan Ferguson
|
||||
--autoquit, -q
|
||||
Toggle automatically quitting after the last client window has
|
||||
closed (overriding the config file).
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of either: the GNU General Public License as published
|
||||
by the Free Software Foundation; or the Artistic License.
|
||||
--cluster-file '<filename>', -c '<filename>'
|
||||
Use supplied file as additional cluster file (see also "FILES").
|
||||
|
||||
See http://dev.perl.org/licenses/ for more information.
|
||||
--cols <cols>, -x <cols>
|
||||
Number of columns
|
||||
|
||||
--config-file '<filename>', -C '<filename>'
|
||||
Use supplied file as additional configuration file (see also
|
||||
"FILES").
|
||||
|
||||
--debug [[...] || <INTEGER>]
|
||||
Enable debugging. Either a level can be provided or the option can
|
||||
be repeated multiple times. Maximum level is 9.
|
||||
|
||||
--dump-config, -d
|
||||
Dump the current configuration in the same format used by the
|
||||
$HOME/.clusterssh/config file.
|
||||
|
||||
--evaluate '<[user@]<host>[:port]>', -e '<[user@]<host>[:port]>'
|
||||
Display and evaluate the terminal and connection arguments to
|
||||
display any potential errors. The <hostname> is required to aid the
|
||||
evaluation.
|
||||
|
||||
--fillscreen
|
||||
Resize terminal windows to fill the whole available screen
|
||||
|
||||
--font '<font>', -f '<font>'
|
||||
Specify the font to use in the terminal windows. Use standard X font
|
||||
notation such as "5x8".
|
||||
|
||||
--help, -h
|
||||
Show basic help text and exit
|
||||
|
||||
--list '[tag]', -L '[tag]'
|
||||
List available cluster tags. Tag is optional. If a tag is provided
|
||||
then hosts for that tag are listed. NOTE: format of output changes
|
||||
when using "--quiet" or "-Q" option.
|
||||
|
||||
--man, -H
|
||||
Show full help text (the man page) and exit
|
||||
|
||||
--options '<STRING>', -o '<STRING>'
|
||||
Specify arguments to be passed to ssh when making the connection.
|
||||
NOTE: options for ssh should normally be put into the ssh
|
||||
configuration file; see "ssh_config" and $HOME/.ssh/config for more
|
||||
details.
|
||||
|
||||
Default: -x -o ConnectTimeout=10
|
||||
|
||||
--port <port>, -p <port>
|
||||
Specify an alternate port for connections.
|
||||
|
||||
--quiet, -Q
|
||||
Do not output extra text when using some options
|
||||
|
||||
--rows <rows>, -y <rows>
|
||||
Number of rows
|
||||
|
||||
--show-history, -s
|
||||
Show history within console window.
|
||||
|
||||
--tag-file '<filename>', -r '<filename>'
|
||||
Use supplied file as additional tag file (see also "FILES")
|
||||
|
||||
--term-args '<STRING>', -t '<STRING>'
|
||||
Specify arguments to be passed to terminals being used.
|
||||
|
||||
--tile, -g
|
||||
Toggle window tiling (overriding the config file).
|
||||
|
||||
--title '<title>', -T '<title>'
|
||||
Specify the initial part of the title used in the console and client
|
||||
windows.
|
||||
|
||||
--unique-servers, -u
|
||||
Toggle connecting to each host only once when a hostname has been
|
||||
specified multiple times.
|
||||
|
||||
--usage, -?
|
||||
Show synopsis and exit
|
||||
|
||||
--use-all-a-records, -A
|
||||
If a hostname resolves to multiple IP addresses, toggle whether or
|
||||
not to connect to all of them, or just the first one (see also
|
||||
config file entry).
|
||||
|
||||
--username '<username>', -l '<username>'
|
||||
Specify the default username to use for connections (if different
|
||||
from the currently logged in user). NOTE: will be overridden by
|
||||
<user>@<host>.
|
||||
|
||||
--version, -v
|
||||
Show version information and exit
|
||||
|
||||
ARGUMENTS
|
||||
The following arguments are supported:
|
||||
|
||||
[user@]<hostname>[:port] ...
|
||||
Open an xterm to the given hostname and connect to the
|
||||
administration console. The optional port number can be used if the
|
||||
server is not listening on the standard port.
|
||||
|
||||
<tag> ...
|
||||
Open a series of xterms defined by <tag> in one of the supplementary
|
||||
configuration files (see "FILES").
|
||||
|
||||
Note: specifying a username on a cluster tag will override any
|
||||
usernames defined in the cluster.
|
||||
|
||||
KEY SHORTCUTS
|
||||
The following key shortcuts are available within the console window, and
|
||||
all of them may be changed via the configuration files.
|
||||
|
||||
Control-Shift-plus
|
||||
Open the 'Add Host(s) or Cluster(s)' dialogue box. Multiple host or
|
||||
cluster names can be entered, separated by spaces.
|
||||
|
||||
Alt-n
|
||||
Paste in the hostname part of the specific connection string to each
|
||||
client, minus any username or port, e.g.
|
||||
|
||||
"scp /etc/hosts server:files/<Alt-n>.hosts"
|
||||
|
||||
would replace the <Alt-n> with the client's name in each window.
|
||||
|
||||
Alt-l
|
||||
Paste in the hostname of the server cssh is being run on
|
||||
|
||||
Alt-q
|
||||
Quit the program and close all connections and windows.
|
||||
|
||||
Alt-r
|
||||
Retile all the client windows.
|
||||
|
||||
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
|
||||
|
||||
Open up a session to a cluster of servers identified by the tag 'farm1'
|
||||
and give the controlling window a specific title, where the tag is
|
||||
defined in one of the default configuration files
|
||||
$ cssh -T 'Web Farm Cluster 1' farm1
|
||||
|
||||
Connect to different servers using different login names. NOTE: this can
|
||||
also be achieved by setting up appropriate options in the configuration
|
||||
files. Do not close the console when the last terminal exits.
|
||||
$ cssh user1@server1 admin@server2
|
||||
|
||||
Open up a cluster defined in a non-default configuration file
|
||||
$ cssh -c $HOME/cssh.extra_clusters db_cluster
|
||||
|
||||
Override the configured/default port to use 2022 instead
|
||||
$ cssh -p 2022 server1 server2
|
||||
|
||||
FILES
|
||||
/etc/clusters, $HOME/.clusterssh/clusters
|
||||
These files contain a list of tags to server names mappings. When
|
||||
any name is used on the command line it is checked to see if it is a
|
||||
tag. If it is a tag, then the tag is replaced with the list of
|
||||
servers. The format is as follows:
|
||||
|
||||
<tag> [user@]<server>[:port] [user@]<server>[:port] [...]
|
||||
|
||||
e.g.
|
||||
|
||||
# List of servers in live
|
||||
live admin1@server1 admin2@server2:2022 server3 server4
|
||||
|
||||
All comments (marked by a #) and blank lines are ignored. Tags may
|
||||
be nested, but be aware of using recursive tags as they are not
|
||||
checked for.
|
||||
|
||||
Servers can be defined using expansion macros:
|
||||
|
||||
"webservers websvr{a,b,c}"
|
||||
|
||||
would be expanded to
|
||||
|
||||
"webservers websvra websvrb websvrc"
|
||||
|
||||
and
|
||||
|
||||
"webservers websvr{6..9}"
|
||||
|
||||
would be expanded to
|
||||
|
||||
"webservers websvr6 websvr7 websvr8 websvr9"
|
||||
|
||||
Extra cluster files may also be specified either as an option on the
|
||||
command line (see "cluster-file") or in the user's
|
||||
$HOME/.clusterssh/config file (see "extra_cluster_file"
|
||||
configuration option).
|
||||
|
||||
NOTE: the last tag read overwrites any pre-existing tag of that
|
||||
name.
|
||||
|
||||
NOTE: there is a special cluster tag called "default" - any tags or
|
||||
hosts included within this tag will be automatically opened if
|
||||
nothing is specified on the command line.
|
||||
|
||||
/etc/tags, $HOME/.clusterssh/tags
|
||||
Very similar to clusters files but the definition is reversed. The
|
||||
format is:
|
||||
|
||||
<host> <tag> [...]
|
||||
|
||||
This allows one host to be specified as a member of a number of
|
||||
tags. This format can be clearer than using clusters files.
|
||||
|
||||
Extra tag files may be specified either as an option (see
|
||||
"tag-file") or within the user's $HOME/.clusterssh/config file (see
|
||||
"extra_tag_file" configuration option).
|
||||
|
||||
NOTE: All tags are added together
|
||||
|
||||
/etc/csshrc & $HOME/.clusterssh/config
|
||||
This file contains configuration overrides - the defaults are as
|
||||
marked. Default options are overwritten first by the global file,
|
||||
and then by the user file.
|
||||
|
||||
NOTE: values for entries do not need to be quoted unless it is
|
||||
required for passing arguments, e.g.
|
||||
|
||||
"terminal_allow_send_events="-xrm '*.VT100.allowSendEvents:true'""
|
||||
|
||||
should be written as
|
||||
|
||||
"terminal_allow_send_events=-xrm '*.VT100.allowSendEvents:true'"
|
||||
|
||||
auto_close = 5
|
||||
Close terminal window after this many seconds. If set to 0 will
|
||||
instead wait on input from the user in each window before
|
||||
closing. See also --autoclose and --no-autoclose
|
||||
|
||||
auto_quit = 1
|
||||
Automatically quit after the last client window closes. Set to 0
|
||||
to disable. See also --autoquit
|
||||
|
||||
auto_wm_decoration_offsets = no
|
||||
Enable or disable alternative algorithm for calculating terminal
|
||||
positioning.
|
||||
|
||||
command_pre =
|
||||
command_post =
|
||||
Add extra commands around the communication method. For example:
|
||||
|
||||
command_pre= . $HOME/virtualenvs/default/bin/active ;
|
||||
command_post= | ct
|
||||
|
||||
would allow for using Python virtual envronments and then piping
|
||||
all shell output through "chromaterm" for syntax highlighting.
|
||||
Note: you must use appropriate command separators/terminators to
|
||||
keep the meaning of the command pipline (such as ";" and "|"
|
||||
between commands).
|
||||
|
||||
These are not put through macro parsing.
|
||||
|
||||
comms = ssh
|
||||
Sets the default communication method (initially taken from the
|
||||
name of the program, but can be overridden here).
|
||||
|
||||
console_position = <null>
|
||||
Set the initial position of the console - if empty then let the
|
||||
window manager decide. Format is '+<x>+<y>', i.e. '+0+0' is top
|
||||
left hand corner of the screen, '+0-70' is bottom left hand side
|
||||
of screen (more or less).
|
||||
|
||||
external_command_mode = 0600
|
||||
File mode bits for the external_command_pipe.
|
||||
|
||||
external_command_pipe = <null>
|
||||
Define the full path to an external command pipe that can be
|
||||
written to for controlling some aspects of ClusterSSH, such as
|
||||
opening sessions to more clusters.
|
||||
|
||||
Commands:
|
||||
|
||||
"open <tag|hostname>" - open new sessions to provided tag or
|
||||
hostname
|
||||
|
||||
"retile" - force window retiling
|
||||
|
||||
e.g.: "echo 'open localhost'" /path/to/external_command_pipe >>
|
||||
|
||||
external_cluster_command = <null>
|
||||
Define the full path to an external command that can be used to
|
||||
resolve tags to host names. This command can be written in any
|
||||
language. The script must accept a list of tags to resolve and
|
||||
output a list of hosts (space separated on a single line). Any
|
||||
tags that cannot be resolved should be returned unchanged.
|
||||
|
||||
A non-0 exit code will be counted as an error, a warning will be
|
||||
printed and output ignored.
|
||||
|
||||
If the external command is given a "-L" option it should output
|
||||
a list of tags (space separated on a single line) it can resolve
|
||||
|
||||
extra_cluster_file = <null>
|
||||
Define an extra cluster file in the format of /etc/clusters.
|
||||
Multiple files can be specified, separated by commas. Both ~ and
|
||||
$HOME are acceptable as a reference to the user's home
|
||||
directory, e.g.
|
||||
|
||||
"extra_cluster_file = ~/clusters, $HOME/clus"
|
||||
|
||||
extra_tag_file = <null>
|
||||
Define an extra tag file in the format of /etc/tags. Multiple
|
||||
files can be specified, separated by commas. Both ~ and $HOME
|
||||
are acceptable as a reference to the user's home directory, e.g.
|
||||
|
||||
"extra_tag_file = ~/tags, $HOME/tags"
|
||||
|
||||
key_addhost = Control-Shift-plus
|
||||
Default key sequence to open AddHost menu. See "KEY SHORTCUTS"
|
||||
for more information.
|
||||
|
||||
hide_menu = 0
|
||||
If set to 1, hide the menu bar (File, Hosts, Send, Help) in the
|
||||
console.
|
||||
|
||||
key_clientname = Alt-n
|
||||
Default key sequence to send cssh client names to client. See
|
||||
"KEY SHORTCUTS" for more information.
|
||||
|
||||
key_localname = Alt-l
|
||||
Default key sequence to send hostname of local server to client.
|
||||
See "KEY SHORTCUTS" for more information.
|
||||
|
||||
key_paste = Control-v
|
||||
Default key sequence to paste text into the console window. See
|
||||
"KEY SHORTCUTS" for more information.
|
||||
|
||||
key_quit = Control-q
|
||||
Default key sequence to quit the program (will terminate all
|
||||
open windows). See "KEY SHORTCUTS" for more information.
|
||||
|
||||
key_retilehosts = Alt-r
|
||||
Default key sequence to retile host windows. See "KEY SHORTCUTS"
|
||||
for more information.
|
||||
|
||||
key_username = Alt-u
|
||||
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.
|
||||
|
||||
max_addhost_menu_cluster_items = 6
|
||||
Maximum number of entries in the 'Add Host' menu cluster list
|
||||
before scrollbars are used
|
||||
|
||||
max_host_menu_items = 30
|
||||
Maximum number of hosts to put into the host menu before
|
||||
starting a new column
|
||||
|
||||
menu_host_autotearoff = 0
|
||||
menu_send_autotearoff = 0
|
||||
When set to non-0 will automatically tear-off the host or send
|
||||
menu at program start
|
||||
|
||||
mouse_paste = Button-2 (middle mouse button)
|
||||
Default key sequence to paste text into the console window using
|
||||
the mouse. See "KEY SHORTCUTS" for more information.
|
||||
|
||||
rsh = /path/to/rsh
|
||||
ssh = /path/to/ssh
|
||||
telnet = /path/to/telnet
|
||||
Set the path to the specific binary to use for the communication
|
||||
method, else uses the first match found in $PATH
|
||||
|
||||
rsh_args = <blank>
|
||||
ssh_args = "-x -o ConnectTimeout=10"
|
||||
telnet_args = <blank>
|
||||
Sets any arguments to be used with the communication method
|
||||
(defaults to ssh arguments).
|
||||
|
||||
NOTE: The given defaults are based on OpenSSH, not commercial
|
||||
ssh software.
|
||||
|
||||
NOTE: Any "generic" change to the method (e.g., specifying the
|
||||
ssh port to use) should be done in the medium's own config file
|
||||
(see "ssh_config" and $HOME/.ssh/config).
|
||||
|
||||
screen_reserve_top = 0
|
||||
screen_reserve_bottom = 60
|
||||
screen_reserve_left = 0
|
||||
screen_reserve_right = 0
|
||||
Number of pixels from the screen's side to reserve when
|
||||
calculating screen geometry for tiling. Setting this to
|
||||
something like 50 will help keep cssh from positioning windows
|
||||
over your window manager's menu bar if it draws one at that side
|
||||
of the screen.
|
||||
|
||||
terminal = /path/to/xterm
|
||||
Path to the X-Windows terminal used for the client.
|
||||
|
||||
terminal_args = <blank>
|
||||
Arguments to use when opening terminal windows. Otherwise takes
|
||||
defaults from $HOME/.Xdefaults or $HOME/.Xresources file.
|
||||
|
||||
terminal_chdir = 0
|
||||
When non-0, set the working directory for each terminal as per
|
||||
'terminal_chdir_path'
|
||||
|
||||
terminal_chdir_path = $HOME/.clusterssh/work/%s
|
||||
Path to use as working directory for each terminal when
|
||||
'terminal_chdir' is enabled. The path provided is passed through
|
||||
the macro parser (see the section above on 'macros_enabled'.
|
||||
|
||||
terminal_font = 6x13
|
||||
Font to use in the terminal windows. Use standard X font
|
||||
notation.
|
||||
|
||||
terminal_reserve_top = 5
|
||||
terminal_reserve_bottom = 0
|
||||
terminal_reserve_left = 5
|
||||
terminal_reserve_right = 0
|
||||
Number of pixels from the terminal's side to reserve when
|
||||
calculating screen geometry for tiling. Setting these will help
|
||||
keep cssh from positioning windows over your scroll and title
|
||||
bars or otherwise overlapping the windows too much.
|
||||
|
||||
terminal_colorize = 1
|
||||
If set to 1 (the default), then "-bg" and "-fg" arguments will
|
||||
be added to the terminal invocation command-line. The terminal
|
||||
will be colored in a pseudo-random way based on the host name;
|
||||
while the color of a terminal is not easily predicted, it will
|
||||
always be the same color for a given host name. After a while,
|
||||
you will recognize hosts by their characteristic terminal color.
|
||||
|
||||
terminal_bg_style = dark
|
||||
If set to "dark", the terminal background will be set to black
|
||||
and the foreground to the pseudo-random color. If set to
|
||||
"light", then the foreground will be black and the background
|
||||
the pseudo-random color. If terminal_colorize is "zero", then
|
||||
this option has no effect.
|
||||
|
||||
terminal_size = 80x24
|
||||
Initial size of terminals to use. NOTE: the number of lines (24)
|
||||
will be decreased when resizing terminals for tiling, not the
|
||||
number of characters (80).
|
||||
|
||||
terminal_title_opt = -T
|
||||
Option used with "terminal" to set the title of the window
|
||||
|
||||
terminal_allow_send_events = -xrm '*.VT100.allowSendEvents:true'
|
||||
Option required by the terminal to allow XSendEvents to be
|
||||
received
|
||||
|
||||
title = cssh
|
||||
Title of windows to use for both the console and terminals.
|
||||
|
||||
unmap_on_redraw = no
|
||||
Tell Tk to use the UnmapWindow request before redrawing terminal
|
||||
windows. This defaults to "no" as it causes some problems with
|
||||
the FVWM window manager. If you are experiencing problems with
|
||||
redraws, you can set it to "yes" to allow the window to be
|
||||
unmapped before it is repositioned.
|
||||
|
||||
use_all_a_records = 0
|
||||
If a hostname resolves to multiple IP addresses, set to 1 to
|
||||
connect to all of them, not just the first one found. See also
|
||||
"--use-all-a-records"}
|
||||
|
||||
use_hotkeys = 1
|
||||
Setting to 0 will disable all hotkeys.
|
||||
|
||||
use_natural_sort = 0
|
||||
Windows will normally sort in alphabetical order, i.e.: host1,
|
||||
host11, host2. Setting to this 1 will change the sort order,
|
||||
i.e.: host1, host2, host11. NOTE: You must have the perl module
|
||||
Sort::Naturally installed.
|
||||
|
||||
user = $LOGNAME
|
||||
Sets the default user for running commands on clients.
|
||||
|
||||
window_tiling = 1
|
||||
Perform window tiling (set to 0 to disable)
|
||||
|
||||
window_tiling_direction = right
|
||||
Direction to tile windows, where "right" means starting top left
|
||||
and moving right and then down, and anything else means starting
|
||||
bottom right and moving left and then up
|
||||
|
||||
NOTE: The key shortcut modifiers must be in the form "Control",
|
||||
"Alt" or "Shift", e.g. with the first letter capitalised and the
|
||||
rest lower case. Keys may also be disabled individually by setting
|
||||
to the word "null".
|
||||
|
||||
$HOME/.clusterssh/send_menu
|
||||
This (optional) file contains items to populate the send menu. The
|
||||
default entry could be written as:
|
||||
|
||||
<send_menu>
|
||||
<menu title="Use Macros">
|
||||
<toggle/>
|
||||
<accelerator>ALT-p</accelerator>
|
||||
</menu>
|
||||
<menu title="Remote Hostname">
|
||||
<command>%s</command>
|
||||
<accelerator>ALT-n</accelerator>
|
||||
</menu>
|
||||
<menu title="Local Hostname">
|
||||
<command>%s</command>
|
||||
<accelerator>ALT-l</accelerator>
|
||||
</menu>
|
||||
<menu title="Username">
|
||||
<command>%u</command>
|
||||
<accelerator>ALT-u</accelerator>
|
||||
</menu>
|
||||
<menu title="Test Text">
|
||||
<command>echo "ClusterSSH Version: %v%n</command>
|
||||
</menu>
|
||||
</send_menu>
|
||||
|
||||
Submenus can also be specified as follows:
|
||||
|
||||
<send_menu>
|
||||
<menu title="Default Entries">
|
||||
<detach>yes</detach>
|
||||
<menu title="Hostname">
|
||||
<command>%s</command>
|
||||
<accelerator>ALT-n</accelerator>
|
||||
</menu>
|
||||
</menu>
|
||||
</send_menu>
|
||||
|
||||
Caveats:
|
||||
|
||||
There is currently no strict format checking of this file.
|
||||
The format of the file may change in the future
|
||||
If the file exists, the default entry (Hostname) is not added
|
||||
|
||||
The following replacement macros are available (note: these can be
|
||||
changed in the configuration file):
|
||||
|
||||
%s Hostname part of the specific connection string to each client,
|
||||
minus any username or port
|
||||
|
||||
%u Username part of the connection string to each client
|
||||
|
||||
%h Hostname of server where cssh is being run from
|
||||
|
||||
%n "RETURN" code
|
||||
|
||||
NOTE: requires XML::Simple to be installed
|
||||
|
||||
KNOWN BUGS
|
||||
If you have any ideas about how to fix the below bugs, please get in
|
||||
touch and/or provide a patch.
|
||||
|
||||
* Swapping virtual desktops can cause a redraw of all the terminal
|
||||
windows. This is due to a lack of distinction within Tk between
|
||||
switching desktops and minimising/maximising windows. Until Tk can
|
||||
tell the difference between the two events, there is no fix (apart
|
||||
from rewriting everything directly in X).
|
||||
|
||||
TROUBLESHOOTING
|
||||
If you have issues running cssh, first try:
|
||||
|
||||
"cssh -e [user@]<hostname>[:port]"
|
||||
|
||||
This performs two tests to confirm cssh is able to work properly with
|
||||
the settings provided within the $HOME/.clusterssh/config file (or
|
||||
internal defaults).
|
||||
|
||||
1 Test the terminal window works with the options provided
|
||||
|
||||
2 Test ssh works to a host with the configured arguments
|
||||
|
||||
Configuration options to watch for in ssh are:
|
||||
|
||||
* SSH doesn't understand "-o ConnectTimeout=10" - remove the option
|
||||
from the $HOME/.clusterssh/config file
|
||||
|
||||
* OpenSSH-3.8 using untrusted ssh tunnels - use "-Y" instead of "-X"
|
||||
or use "ForwardX11Trusted yes" in $HOME/.ssh/ssh_config (if you
|
||||
change the default ssh options from "-x" to "-X")
|
||||
|
||||
SUPPORT AND REPORTING BUGS
|
||||
A web site for comments, requests, bug reports and bug fixes/patches is
|
||||
available at: <https://github.com/duncs/clusterssh>
|
||||
|
||||
If you require support, please run the following commands and create an
|
||||
issue via: <https://github.com/duncs/clusterssh/issues>
|
||||
|
||||
"perl -V"
|
||||
|
||||
"perl -MTk -e 'print $Tk::VERSION,$/'"
|
||||
|
||||
"perl -MX11::Protocol -e 'print $X11::Protocol::VERSION,$/'"
|
||||
|
||||
"cat /etc/csshrc $HOME/.clusterssh/config"
|
||||
|
||||
Using the debug option (--debug) will turn on debugging output. Repeat
|
||||
the option to increase the amount of debug. However, if possible please
|
||||
only use this option with one host at a time, e.g. "cssh --debug <host>"
|
||||
due to the amount of output produced (in both main and child windows).
|
||||
|
||||
SEE ALSO
|
||||
<https://github.com/duncs/clusterssh/wiki/>, "ssh", Tk::overview,
|
||||
X11::Protocol, "perl"
|
||||
|
||||
AUTHOR
|
||||
Duncan Ferguson, "<duncan_j_ferguson at yahoo.co.uk>"
|
||||
|
||||
LICENSE AND COPYRIGHT
|
||||
Copyright 1999-2018 Duncan Ferguson.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of either: the GNU General Public License as published
|
||||
by the Free Software Foundation; or the Artistic License.
|
||||
|
||||
See http://dev.perl.org/licenses/ for more information.
|
||||
|
||||
|
|
8
THANKS
8
THANKS
|
@ -41,3 +41,11 @@ Stefan Steiner
|
|||
Ryan Brown
|
||||
Brandon Perkins
|
||||
Oliver Meissner
|
||||
Andrew Stevenson (cqexbesd)
|
||||
Emanuele Tomasi
|
||||
Deny Dias
|
||||
Bill Rushmore
|
||||
Ankit Vadehra
|
||||
Azenet
|
||||
Markus Frosch (lazyfrosch)
|
||||
Petr Vorel
|
||||
|
|
45
TODO
45
TODO
|
@ -1,52 +1,15 @@
|
|||
Overview of tasks
|
||||
=================
|
||||
|
||||
Config file
|
||||
===========
|
||||
|
||||
Convert from file ~/.cssrch to directory ~/.clusterssh
|
||||
For conversion process
|
||||
- clusters in .csshrc should be placed into 'default.cluster'
|
||||
- all other config should go into 'config'
|
||||
- create default menu file
|
||||
|
||||
New feature - if cssh -s symlinked to c_xxx then search for xxx as a cluster
|
||||
file in .clutersshrc and open that
|
||||
|
||||
Getopts usage
|
||||
=============
|
||||
|
||||
Set up similar to Nagios::Plugin where Getopts::Long is subclassed
|
||||
Sort out docs too
|
||||
|
||||
Add in '-l' to list all available tags
|
||||
Add in '-l <tag>' to list all hosts for the given tag
|
||||
Idea from Markus Manzke
|
||||
|
||||
Change way commands generated
|
||||
=============================
|
||||
|
||||
Each script file (cssh, crsh, ctel, ccon, cscp, crsync) should define how
|
||||
the command is created/used and also none-common options
|
||||
|
||||
# Something like the following (needs refinement):
|
||||
|
||||
$app->setup_command(
|
||||
"ssh %PORT% %USER% %HOSTNAME%",
|
||||
{
|
||||
%PORT% => [ $app->getopt->port, "-p %PORT%" ],
|
||||
%USER% => [ $app->getopt->username, "-l %USER%" ],
|
||||
}
|
||||
)
|
||||
|
||||
Change way terminal windows are created
|
||||
=======================================
|
||||
|
||||
Set up terminal windows in Tk to embedd termainl session into it, such as with
|
||||
xterm
|
||||
Set up terminal windows in Tk to embed termainal session into it, such
|
||||
as with xterm:
|
||||
|
||||
xterm -wid <wid> ....
|
||||
|
||||
This may limit to terminal thats can reparent into a given window id though.
|
||||
This may limit what terminals can be used, though
|
||||
|
||||
See also:
|
||||
http://www.perlmonks.org/?node_id=359764
|
||||
|
|
1
bin/ccon
1
bin/ccon
|
@ -1 +0,0 @@
|
|||
cssh
|
1
bin/crsh
1
bin/crsh
|
@ -1 +0,0 @@
|
|||
cssh
|
881
bin/cssh
881
bin/cssh
|
@ -1,881 +0,0 @@
|
|||
#!/usr/bin/perl
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use FindBin;
|
||||
use lib $FindBin::Bin. '/../lib';
|
||||
use lib $FindBin::Bin. '/../lib/perl5';
|
||||
use App::ClusterSSH;
|
||||
|
||||
my $app = App::ClusterSSH->new();
|
||||
$app->run();
|
||||
|
||||
__END__
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
cssh, crsh, ctel, ccon - Cluster administration tool
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
S<< cssh [options] [[user@]<server>[:port]|<tag>] [...] >>
|
||||
S<< crsh [options] [[user@]<server>[:port]|<tag>] [...] >>
|
||||
S<< ctel [options] [<server>[:port]|<tag>] [...] >>
|
||||
S<< ccon [options] [[user@]<server>[:port]|<tag>] [...] >>
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
The command opens an administration console and an xterm to all specified
|
||||
hosts. Any text typed into the administration console is replicated to
|
||||
all windows. All windows may also be typed into directly.
|
||||
|
||||
This tool is intended for (but not limited to) cluster administration where
|
||||
the same configuration or commands must be run on each node within the
|
||||
cluster. Performing these commands all at once via this tool ensures all
|
||||
nodes are kept in sync.
|
||||
|
||||
Connections are opened via ssh so a correctly installed and configured
|
||||
ssh installation is required. If, however, the program is called by "crsh"
|
||||
then the rsh protocol is used (and the communications channel is insecure),
|
||||
or by "ctel" then telnet is used, or by "ccon" then console is used.
|
||||
|
||||
Extra caution should be taken when editing system files such as
|
||||
/etc/inet/hosts as lines may not necessarily be in the same order. Assuming
|
||||
line 5 is the same across all servers and modifying that is dangerous.
|
||||
Better to search for the specific line to be changed and double-check before
|
||||
changes are committed.
|
||||
|
||||
=head2 Further Notes
|
||||
|
||||
Please also see L</KNOWN BUGS>.
|
||||
|
||||
=over
|
||||
|
||||
=item *
|
||||
|
||||
The dotted line on any sub-menu is a tear-off, i.e. click on it
|
||||
and the sub-menu is turned into its own window.
|
||||
|
||||
=item *
|
||||
|
||||
Unchecking a hostname on the Hosts sub-menu will unplug the host from the
|
||||
cluster control window, so any text typed into the console is not sent to
|
||||
that host. Re-selecting it will plug it back in.
|
||||
|
||||
=item *
|
||||
|
||||
If your window manager menu bars are obscured by terminal windows see
|
||||
the C<screen_reserve_XXXXX> options in the F<$HOME/.clusterssh/config> file (see L</"FILES">).
|
||||
|
||||
=item *
|
||||
|
||||
If the terminals overlap too much see the C<terminal_reserve_XXXXX>
|
||||
options in the F<$HOME/.clusterssh/config> file (see L</"FILES">).
|
||||
|
||||
=item *
|
||||
|
||||
If the code is called as crsh instead of cssh (i.e. a symlink called
|
||||
crsh points to the cssh file or the file is renamed) rsh is used as the
|
||||
communications protocol instead of ssh.
|
||||
|
||||
=item *
|
||||
|
||||
If the code is called as ctel instead of cssh (i.e. a symlink called
|
||||
ctel points to the cssh file or the file is renamed) telnet is used as the
|
||||
communications protocol instead of ssh.
|
||||
|
||||
=item *
|
||||
|
||||
If the code is called as ccon instead of cssh (i.e. a symlink called
|
||||
ccon points to the cssh file or the file is renamed) console is used as the
|
||||
communications protocol instead of ssh.
|
||||
|
||||
=item *
|
||||
|
||||
When using cssh on a large number of systems to connect back to a single
|
||||
system (e.g. you issue a command to the cluster to scp a file from a given
|
||||
location) and when these connections require authentication (i.e. you are
|
||||
going to authenticate with a password), the sshd daemon at that location
|
||||
may refuse connects after the number specified by MaxStartups in
|
||||
sshd_config is exceeded. (If this value is not set, it defaults to 10.)
|
||||
This is expected behavior; sshd uses this mechanism to prevent DoS attacks
|
||||
from unauthenticated sources. Please tune sshd_config and reload the SSH
|
||||
daemon, or consider using the ~/.ssh/authorized_keys mechanism for
|
||||
authentication if you encounter this problem.
|
||||
|
||||
=item *
|
||||
|
||||
If client windows fail to open, try running:
|
||||
|
||||
C<< cssh -e {single host name} >>
|
||||
|
||||
This will test the mechanisms used to open windows to hosts. This could
|
||||
be due to either the C<-xrm> terminal option which enables C<AllowSendEvents>
|
||||
(some terminal do not require this option, other terminals have another
|
||||
method for enabling it - see your terminal documention) or the
|
||||
C<ConnectTimeout> ssh option (see the configuration option C<-o> or file
|
||||
C<$HOME/.clusterssh/config> below to resolve this).
|
||||
|
||||
=back
|
||||
|
||||
=head1 OPTIONS
|
||||
|
||||
Some of these options may also be defined within the configuration file.
|
||||
Default options are shown as appropriate.
|
||||
|
||||
=over
|
||||
|
||||
=item --action,-a '<command>'
|
||||
|
||||
Run the command in each session, i.e. C<-a 'vi /etc/hosts'> to drop straight
|
||||
into a vi session. NOTE: not all communications methods support this (ssh
|
||||
and rsh should, telnet and console will not).
|
||||
|
||||
=item --autoclose,-A <seconds>
|
||||
|
||||
Number of seconds to wait before closing finished terminal windows.
|
||||
|
||||
=item --autoquit,-q|--no-autoquit,-Q
|
||||
|
||||
Enable|Disable automatically quiting after the last client window has closed
|
||||
(overriding the config file)
|
||||
|
||||
=item --cluster-file,-c <file>
|
||||
|
||||
Use supplied file as additional cluster file (see also L</"FILES">)
|
||||
|
||||
=item --config-file,-C <file>
|
||||
|
||||
Use supplied file as additional configuration file (see also L</"FILES">)
|
||||
|
||||
=item -d
|
||||
|
||||
DEPRECATED. See '--debug'.
|
||||
|
||||
=item -D
|
||||
|
||||
DEPRECATED. See '--debug'.
|
||||
|
||||
=item --debug [number].
|
||||
|
||||
Enable debugging. Either a level can be provided or the option can be
|
||||
repeated multiple times. Maximum level is 4.
|
||||
|
||||
=item --evaluate,-e [user@]<hostname>[:port]
|
||||
|
||||
Display and evaluate the terminal and connection arguments so display any
|
||||
potential errors. The <hostname> is required to aid the evaluation.
|
||||
|
||||
=item --font,-f "5x8"
|
||||
|
||||
Specify the font to use in the terminal windows. Use standard X font notation.
|
||||
|
||||
=item --help,-h|-?
|
||||
|
||||
Show basic help text, and exit
|
||||
|
||||
=item --list, -L
|
||||
|
||||
List available cluster tags.
|
||||
|
||||
=item --man,-H
|
||||
|
||||
Show full help test (the man page), and exit
|
||||
|
||||
=item --master,-M <master>
|
||||
|
||||
The console client program polls master as the primary server, rather than the
|
||||
default set at compile time (typically ``console'').
|
||||
|
||||
=item --options,-o "-x -o ConnectTimeout=10" - for ssh connections
|
||||
|
||||
=item --options,-o "" - for rsh connections
|
||||
|
||||
Specify arguments to be passed to ssh or rsh when making the connection.
|
||||
|
||||
B<NOTE:> any "generic" change to the method (i.e. specifying the ssh port to use)
|
||||
should be done in the medium's own config file (see C<ssh_config> and
|
||||
F<$HOME/.ssh/config>).
|
||||
|
||||
=item --output-config,-u
|
||||
|
||||
Output the current configuration in the same format used by the
|
||||
F<$HOME/.clusterssh/config> file.
|
||||
|
||||
=item --port,-p <port>
|
||||
|
||||
Specify an alternate port for connections.
|
||||
|
||||
=item --show-history,-s
|
||||
|
||||
IN BETA: Show history within console window. This code is still being
|
||||
worked upon, but may help some users.
|
||||
|
||||
=item --tag-file,-c <file>
|
||||
|
||||
Use supplied file as additional tag file (see also L</"FILES">)
|
||||
|
||||
=item --term-args,-t ""
|
||||
|
||||
Specify arguments to be passed to terminals being used
|
||||
|
||||
=item --tile,-g|--no-tile,-G
|
||||
|
||||
Enable|Disable window tiling (overriding the config file)
|
||||
|
||||
=item --title,-T "CSSH"
|
||||
|
||||
Specify the initial part of the title used in the console and client windows
|
||||
|
||||
=item --unique-servers,-m
|
||||
|
||||
Connect to each host only once
|
||||
|
||||
=item --use_all_a_records,-A
|
||||
|
||||
If a hostname resolves to multiple IP addresses, toggle whether or not to
|
||||
connect to all of them, or just the first one (see also config file entry)
|
||||
|
||||
=item --username,-l $LOGNAME
|
||||
|
||||
Specify the default username to use for connections (if different from the
|
||||
currently logged in user). B<NOTE:> will be overridden by <user>@<host>
|
||||
|
||||
=item --version,-v
|
||||
|
||||
Show version information and exit
|
||||
|
||||
=back
|
||||
|
||||
=head1 ARGUMENTS
|
||||
|
||||
The following arguments are support:
|
||||
|
||||
=over
|
||||
|
||||
=item [user@]<hostname>[:port] ...
|
||||
|
||||
Open an xterm to the given hostname and connect to the administration
|
||||
console. An optional port number can be used if sshd is not listening
|
||||
on standard port (e.g not listening on port 22) and ssh_config cannot be used.
|
||||
|
||||
=item <tag> ...
|
||||
|
||||
Open a series of xterms defined by <tag> in one of the suplimentary
|
||||
configuration files (see L</"FILES">).
|
||||
|
||||
Note: specifying a username on a cluster tag will override any usernames
|
||||
defined in the cluster
|
||||
|
||||
=back
|
||||
|
||||
=head1 KEY SHORTCUTS
|
||||
|
||||
The following key shortcuts are available within the console window, and all
|
||||
of them may be changed via the configuration files.
|
||||
|
||||
=over
|
||||
|
||||
=item Control-q
|
||||
|
||||
Quit the program and close all connections and windows
|
||||
|
||||
=item Control-+
|
||||
|
||||
Open the 'Add Host(s) or Cluster(s)' dialogue box. Mutiple host or cluster
|
||||
names can be entered, separated by spaces.
|
||||
|
||||
=item Alt-n
|
||||
|
||||
Paste in the hostname part of the specific connection string to each
|
||||
client, minus any username or port, i.e.
|
||||
|
||||
C<< scp /etc/hosts server:files/<Alt-n>.hosts >>
|
||||
|
||||
would replace the <Alt-n> with the client's name in each window
|
||||
|
||||
=item Alt-r
|
||||
|
||||
Retile all the client windows
|
||||
|
||||
=back
|
||||
|
||||
=head1 EXAMPLES
|
||||
|
||||
=over
|
||||
|
||||
=item Open up a session to 3 servers
|
||||
|
||||
S<$ cssh server1 server2 server3>
|
||||
|
||||
=item Open up a session to a cluster of servers identified by the tag 'farm1'
|
||||
and give the controlling window a specific title, where the cluster is defined
|
||||
in one of the default configuration files
|
||||
|
||||
S<$ cssh -T 'Web Farm Cluster 1' farm1>
|
||||
|
||||
=item Connect to different servers using different login names. NOTE: this can
|
||||
also be achieved by setting up appropriate options in the F<.ssh/config> file.
|
||||
Do not close cssh when last terminal exits.
|
||||
|
||||
S<$ cssh -Q user1@server1 admin@server2>
|
||||
|
||||
=item Open up a cluster defined in a non-default configuration file
|
||||
|
||||
S<$ cssh -c $HOME/cssh.config db_cluster>
|
||||
|
||||
=item Use telnet on port 2022 instead of ssh
|
||||
|
||||
S<$ ctel -p 2022 server1 server2>
|
||||
|
||||
=item Use rsh instead of ssh
|
||||
|
||||
S<$ crsh server1 server2>
|
||||
|
||||
=item Use console with master as the primary server instead of ssh
|
||||
|
||||
S<$ ccon -M master server1 server2>
|
||||
|
||||
=back
|
||||
|
||||
=head1 FILES
|
||||
|
||||
=over
|
||||
|
||||
=item F</etc/clusters>, F<$HOME/.clusterssh/clusters>
|
||||
|
||||
These files contain a list of tags to server names mappings. When any name
|
||||
is used on the command line it is checked to see if it is a tag.
|
||||
If it is a tag, then the tag is replaced with the list of servers. The
|
||||
formated is as follows:
|
||||
|
||||
S<< <tag> [user@]<server> [user@]<server> [...] >>
|
||||
|
||||
i.e.
|
||||
|
||||
# List of servers in live
|
||||
live admin1@server1 admin2@server2 server3 server4
|
||||
|
||||
All comments (marked by a #) and blank lines are ignored. Tags may be
|
||||
nested, but be aware of using recursive tags as they are not checked for.
|
||||
|
||||
Extra cluster files may also be specified either as an option on the
|
||||
command line (see C<cluster-file>) or in the users F<$HOME/.clusterssh/config>
|
||||
file (see C<extra_cluster_file> configuration option).
|
||||
|
||||
NOTE: the last tag read overwrites any pre-existing tag of that name
|
||||
|
||||
NOTE: there is a special cluster tag called C<default> - any tags or hosts
|
||||
included within this tag will be automatically opened if no other tags
|
||||
are specified on the command line.
|
||||
|
||||
=item F</etc/tags>, F<$HOME/.clusterssh/tags>
|
||||
|
||||
Very similar to F<cluster> files but the definition is reversed. The
|
||||
format is:
|
||||
|
||||
S<< <host> <tag> [...] >>
|
||||
|
||||
This allows one host to be specified as a member of a number of tags. This
|
||||
format can be clearer than using F<clusters> files.
|
||||
|
||||
Extra tag files may be spcieid either an an option (see C<tag-file>) or within
|
||||
the users F<$HOME/.clusterssh/config> file (see C<extra_tag_file>
|
||||
configuration option).
|
||||
|
||||
NOTE: All tags are added together
|
||||
|
||||
=item F</etc/csshrc> & F<$HOME/.clusterssh/config>
|
||||
|
||||
This file contains configuration overrides - the defaults are as marked.
|
||||
Default options are overwritten first by the global file, and then by the
|
||||
user file.
|
||||
|
||||
B<NOTE:> values for entries do not need to be quoted unless it is required
|
||||
for passing arguments, i.e.
|
||||
|
||||
terminal_allow_send_events="-xrm '*.VT100.allowSendEvents:true'"
|
||||
|
||||
should be written as
|
||||
|
||||
terminal_allow_send_events=-xrm '*.VT100.allowSendEvents:true'
|
||||
|
||||
=over
|
||||
|
||||
=item auto_close = 5
|
||||
|
||||
Close terminal window after this many seconds. If set to 0 will instead wait
|
||||
on input from the user in each window before closing. Can be overridden
|
||||
by C<-K> on the command line
|
||||
|
||||
=item auto_quit = yes
|
||||
|
||||
Automatically quit after the last client window closes. Set to anything
|
||||
other than "yes" to disable. Can be overridden by C<-Q> on the command line.
|
||||
|
||||
=item clusters = <blank>
|
||||
|
||||
Define a number of cluster tags in addition to (or to replace) tags defined
|
||||
in the F</etc/clusters> file. The format is:
|
||||
|
||||
clusters = <tag1> <tag2> <tag3>
|
||||
<tag1> = host1 host2 host3
|
||||
<tag2> = user@host4 user@host5 host6
|
||||
<tag3> = <tag1> <tag2>
|
||||
|
||||
As with the F</etc/clusters> file, be sure not to create recursivly nested tags.
|
||||
|
||||
=item comms = ssh
|
||||
|
||||
Sets the default communication method (initially taken from the name of
|
||||
program, but can be overridden here).
|
||||
|
||||
=item console_position = <null>
|
||||
|
||||
Set the initial position of the console - if empty then let the window manager
|
||||
decide. Format is '+<x>+<y>', i.e. '+0+0' is top left hand corner of the screen,
|
||||
'+0-70' is bottom left hand side of screen (more or less).
|
||||
|
||||
=item external_cluster_command = <null>
|
||||
|
||||
Define the full path to an external command that can be used to resolve tags
|
||||
to host names. This command can be written in any language. The script must
|
||||
accept a list of tags to resolve and output a list of hosts on a single line.
|
||||
Any tags that cannot be resolved should be returned unchanged.
|
||||
|
||||
A non-0 exit code will be counted as an error, a warning will be printed and
|
||||
output ignored.
|
||||
|
||||
=item extra_cluster_file = <null>
|
||||
|
||||
Define an extra cluster file in the format of F</etc/clusters>. Multiple
|
||||
files can be specified, seperated by commas. Both ~ and $HOME are acceptable
|
||||
as a to reference the users home directory, i.e.
|
||||
|
||||
extra_cluster_file = ~/clusters, $HOME/clus
|
||||
|
||||
=item ignore_host_errors
|
||||
|
||||
THIS OPTION IS DEPRECATED. It has been left in so current systems continue
|
||||
to function as expected.
|
||||
|
||||
=item key_addhost = Control-Shift-plus
|
||||
|
||||
Default key sequence to open AddHost menu. See below notes on shortcuts.
|
||||
|
||||
=item key_clientname = Alt-n
|
||||
|
||||
Default key sequence to send cssh client names to client. See below notes
|
||||
on shortcuts.
|
||||
|
||||
=item key_localname = Alt-l
|
||||
|
||||
Default key sequence to send hostname of local server to client. See below
|
||||
notes on shortcuts.
|
||||
|
||||
=item key_paste = Control-v
|
||||
|
||||
Default key sequence to paste text into the console window. See below notes
|
||||
on shortcuts.
|
||||
|
||||
=item key_quit = Control-q
|
||||
|
||||
Default key sequence to quit the program (will terminate all open windows).
|
||||
See below notes on shortcuts.
|
||||
|
||||
=item key_retilehosts = Alt-r
|
||||
|
||||
Default key sequence to retile host windows. See below notes on shortcuts.
|
||||
|
||||
=item key_username = Alt-u
|
||||
|
||||
Default key sequence to send username to client. See below notes
|
||||
on shortcuts.
|
||||
|
||||
=item macro_servername = %s
|
||||
|
||||
=item macro_hostname = %h
|
||||
|
||||
=item macro_username = %u
|
||||
|
||||
=item macro_newline = %n
|
||||
|
||||
=item macro_version = %v
|
||||
|
||||
Change the replacement macro used when either using a 'Send' menu item, or when
|
||||
pasting text into the main console.
|
||||
|
||||
=item macros_enabled = yes
|
||||
|
||||
Enable or disable macro replacement. Note: this affects pasting into the
|
||||
main console, items on the 'Send' menu and key_clientname, key_localname, key_servername and key_username.
|
||||
|
||||
=item max_addhost_menu_cluster_items = 6
|
||||
|
||||
Maximum number of entries in the 'Add Host' menu cluster list before
|
||||
scrollbars are used
|
||||
|
||||
=item max_host_menu_items = 30
|
||||
|
||||
Maximum number of hosts to put into the host menu before starting a new column
|
||||
|
||||
=item menu_host_autotearoff = 0
|
||||
|
||||
=item menu_send_autotearoff = 0
|
||||
|
||||
When set to non-0 will automatically tear-off the host or send menu at
|
||||
program start
|
||||
|
||||
=item mouse_paste = Button-2 (middle mouse button)
|
||||
|
||||
Default key sequence to paste text into the console window using the mouse.
|
||||
See below notes on shortcuts.
|
||||
|
||||
=item rsh = rsh
|
||||
|
||||
=item ssh = ssh
|
||||
|
||||
=item telnet = telnet
|
||||
|
||||
Set the path to the specific binary to use for the communication method, else
|
||||
uses the first match found in $PATH
|
||||
|
||||
=item rsh_args = <blank>
|
||||
|
||||
=item ssh_args = "-x -o ConnectTimeout=10"
|
||||
|
||||
=item telnet_args = <blank>
|
||||
|
||||
Sets any arguments to be used with the communication method (defaults to ssh
|
||||
arguments).
|
||||
|
||||
B<NOTE:> The given defaults are based on OpenSSH, not commercial ssh software.
|
||||
|
||||
B<NOTE:> Any "generic" change to the method (i.e. specifying the ssh port to use)
|
||||
should be done in the medium's own config file (see C<ssh_config> and
|
||||
F<$HOME/.ssh/config>).
|
||||
|
||||
=item screen_reserve_top = 0
|
||||
|
||||
=item screen_reserve_bottom = 60
|
||||
|
||||
=item screen_reserve_left = 0
|
||||
|
||||
=item screen_reserve_right = 0
|
||||
|
||||
Number of pixels from the screen side to reserve when calculating screen
|
||||
geometry for tiling. Setting this to something like 50 will help keep cssh
|
||||
from positioning windows over your window manager's menu bar if it draws one
|
||||
at that side of the screen.
|
||||
|
||||
=item rsh = /path/to/rsh
|
||||
|
||||
=item ssh = /path/to/ssh
|
||||
|
||||
Depending on the value of comms, set the path of the communication binary.
|
||||
|
||||
=item terminal = /path/to/terminal
|
||||
|
||||
Path to the x-windows terminal used for the client.
|
||||
|
||||
=item terminal_args = <blank>
|
||||
|
||||
Arguments to use when opening terminal windows. Otherwise takes defaults
|
||||
from F<$HOME/.Xdefaults> or $<$HOME/.Xresources> file.
|
||||
|
||||
=item terminal_font = 6x13
|
||||
|
||||
Font to use in the terminal windows. Use standard X font notation.
|
||||
|
||||
=item terminal_reserve_top = 5
|
||||
|
||||
=item terminal_reserve_bottom = 0
|
||||
|
||||
=item terminal_reserve_left = 5
|
||||
|
||||
=item terminal_reserve_right = 0
|
||||
|
||||
Number of pixels from the terminal side to reserve when calculating screen
|
||||
geometry for tiling. Setting these will help keep cssh from positioning
|
||||
windows over your scroll and title bars or otherwise overlapping the windows
|
||||
too much.
|
||||
|
||||
=item terminal_colorize = 1
|
||||
|
||||
If set to 1 (the default), then "-bg" and "-fg" arguments will be added
|
||||
to the terminal invocation command-line. The terminal will be colored
|
||||
in a pseudo-random way based on the host name; while the color of a terminal
|
||||
is not easily predicted, it will always be the same color for a given host
|
||||
name. After a while, you will recognize hosts by their characteristic
|
||||
terminal color.
|
||||
|
||||
=item terminal_bg_style = dark
|
||||
|
||||
If set to dark, the the terminal background will be set to black and
|
||||
the foreground to the pseudo-random color. If set to light, then the
|
||||
foreground will be black and the background the pseudo-random color. If
|
||||
terminal_colorize is zero, then this option has no effect.
|
||||
|
||||
=item terminal_size = 80x24
|
||||
|
||||
Initial size of terminals to use (note: the number of lines (24) will be
|
||||
decreased when resizing terminals for tiling, not the number of characters (80))
|
||||
|
||||
=item terminal_title_opt = -T
|
||||
|
||||
Option used with C<terminal> to set the title of the window
|
||||
|
||||
=item terminal_allow_send_events = -xrm '*.VT100.allowSendEvents:true'
|
||||
|
||||
Option required by the terminal to allow XSendEvents to be received
|
||||
|
||||
=item title = cssh
|
||||
|
||||
Title of windows to use for both the console and terminals.
|
||||
|
||||
=item unmap_on_redraw = no
|
||||
|
||||
Tell Tk to use the UnmapWindow request before redrawing terminal windows.
|
||||
This defaults to "no" as it causes some problems with the FVWM window
|
||||
manager. If you are experiencing problems with redraws, you can set it to
|
||||
"yes" to allow the window to be unmapped before it is repositioned.
|
||||
|
||||
=item use_all_a_records = no
|
||||
|
||||
If a hostname resolves to multiple IP addresses, set to C<yes> to connect
|
||||
to all of them, not just the first one found.
|
||||
|
||||
=item use_hotkeys = yes
|
||||
|
||||
Setting to anything other than C<yes> will disable all hotkeys.
|
||||
|
||||
=item user = $LOGNAME
|
||||
|
||||
Sets the default user for running commands on clients.
|
||||
|
||||
=item window_tiling = yes
|
||||
|
||||
Perform window tiling (set to C<no> to disable)
|
||||
|
||||
=item window_tiling_direction = right
|
||||
|
||||
Direction to tile windows, where "right" means starting top left and moving
|
||||
right and then down, and anything else means starting bottom right and moving
|
||||
left and then up
|
||||
|
||||
=back
|
||||
|
||||
B<NOTE:> The key shortcut modifiers must be in the form "Control", "Alt", or
|
||||
"Shift", i.e. with the first letter capitalised and the rest lower case. Keys
|
||||
may also be disabled individually by setting to the word "null".
|
||||
|
||||
=item F<$HOME/.csshrc_send_menu>
|
||||
|
||||
This (optional) file contains items to populate the send menu. The
|
||||
default entry could be written as:
|
||||
|
||||
<send_menu>
|
||||
<menu title="Use Macros">
|
||||
<toggle/>
|
||||
<accelerator>ALT-p</accelerator>
|
||||
</dmenu>
|
||||
<menu title="Remote Hostname">
|
||||
<command>%s</command>
|
||||
<accelerator>ALT-n</accelerator>
|
||||
</menu>
|
||||
<menu title="Local Hostname">
|
||||
<command>%s</command>
|
||||
<accelerator>ALT-l</accelerator>
|
||||
</menu>
|
||||
<menu title="Username">
|
||||
<command>%u</command>
|
||||
<accelerator>ALT-u</accelerator>
|
||||
</menu>
|
||||
<menu title="Test Text">
|
||||
<command>echo "ClusterSSH Version: %v%n</command>
|
||||
</menu>
|
||||
</send_menu>
|
||||
|
||||
Submenus can also be specified as follows:
|
||||
|
||||
<send_menu>
|
||||
<menu title="Default Entries">
|
||||
<detach>yes</detach>
|
||||
<menu title="Hostname">
|
||||
<command>%s</command>
|
||||
<accelerator>ALT-n</accelerator>
|
||||
</menu>
|
||||
</menu>
|
||||
</send_menu>
|
||||
|
||||
B<Caveats:>
|
||||
|
||||
=over 4
|
||||
|
||||
=item There is currently no strict format checking of this file.
|
||||
|
||||
=item The format of the file may change in the future
|
||||
|
||||
=item If the file exists the default entry (Hostname) is not added
|
||||
|
||||
=back
|
||||
|
||||
The following replacement macros are available (note: these can be changed in the configuration file):
|
||||
|
||||
=over 4
|
||||
|
||||
=item %s
|
||||
|
||||
Hostname part of the specific connection string to each client, minus any
|
||||
username or port
|
||||
|
||||
=item %u
|
||||
|
||||
Username part of the connection string to each client
|
||||
|
||||
=item %h
|
||||
|
||||
Hostname of server where cssh is being run from
|
||||
|
||||
=item %n
|
||||
|
||||
<RETURN> code
|
||||
|
||||
=back
|
||||
|
||||
B<NOTE:> requires L<XML::Simple> to be installed
|
||||
|
||||
=back
|
||||
|
||||
=head1 KNOWN BUGS
|
||||
|
||||
=over 4
|
||||
|
||||
=item 1.
|
||||
|
||||
Catering for IPv6 addresses is minimal. This is due to a conflict
|
||||
between IPv6 addresses and port numbers within the same
|
||||
server definition since they both use the same seperator, i.e. is the
|
||||
following just an IPv6 address, or an address + port number of 2323?
|
||||
|
||||
2001:db8::1428:2323
|
||||
|
||||
Exactly - I cannot tell either. the IPv6 address without a port is assumed
|
||||
in those cases where it cannot be determined and a warning is issued.
|
||||
|
||||
Possible work arounds include:
|
||||
|
||||
=over 4
|
||||
|
||||
=item a.
|
||||
|
||||
Use square brackets around the IPv6 address, i.e.
|
||||
[2001:db8::1428]:2323
|
||||
or
|
||||
[2001:db8::1428:2323]
|
||||
as appropriate so there is no ambiguity
|
||||
|
||||
=item b.
|
||||
|
||||
Use the full IPv6 address if also using a port number - the 8th colon
|
||||
is assumed to be the port seperator.
|
||||
|
||||
=item c.
|
||||
|
||||
Define the IPv6 address in your /etc/hosts file, DNS or other name service
|
||||
lookup mechanism and use the hostname instead of the address.
|
||||
|
||||
=back
|
||||
|
||||
=item 2.
|
||||
|
||||
Swapping virtual desktops can a redraw of all the terminal windows. This
|
||||
is due to a lack of distinction within Tk between switching desktops and
|
||||
minimising/maximising windows. Until Tk can tell the difference between the
|
||||
two events, there is no fix (apart from rewriting everything directly in X)
|
||||
|
||||
=back
|
||||
|
||||
Anyone with any good ideas to fix the above bugs is more than welcome to get
|
||||
in touch and/or provide a patch.
|
||||
|
||||
=head1 REPORTING BUGS
|
||||
|
||||
=over 2
|
||||
|
||||
=item *
|
||||
|
||||
If you have issues running cssh, first try:
|
||||
|
||||
C<< cssh -e [user@]<hostname>[:port] >>
|
||||
|
||||
This performs two tests to confirm cssh is able to work properly with the
|
||||
settings provided within the F<$HOME/.clusterssh/config> file (or internal defaults).
|
||||
|
||||
1. test the terminal window works with the options provided
|
||||
|
||||
2. test ssh works to a host with the configured arguments
|
||||
|
||||
Configuration options to watch for in ssh are
|
||||
|
||||
- Doesnt understand "-o ConnectTimeout=10" - remove the option
|
||||
in the F<$HOME/.clusterssh/config> file
|
||||
|
||||
- OpenSSH-3.8 using untrusted ssh tunnels - use "-Y" instead of "-X"
|
||||
or use "ForwardX11Trusted yes' in ssh_config (if you change the
|
||||
default ssh options from -x to -X)
|
||||
|
||||
=item *
|
||||
|
||||
If you require support, please run the following commands
|
||||
and post it on the web site in the support/problems forum:
|
||||
|
||||
C<< perl -V >>
|
||||
|
||||
C<< perl -MTk -e 'print $Tk::VERSION,$/' >>
|
||||
|
||||
C<< perl -MX11::Protocol -e 'print $X11::Protocol::VERSION,$/' >>
|
||||
|
||||
C<< cat /etc/csshrc $HOME/.clusterssh/config >>
|
||||
|
||||
=item *
|
||||
|
||||
Use the debug switches (-d, -D, or -dD) will turn on debugging output.
|
||||
However, please only use this option with one host at a time,
|
||||
i.e. "cssh -d <host>" due to the amount of output produced (in both main
|
||||
and child windows).
|
||||
|
||||
=back
|
||||
|
||||
=head1 SEE ALSO
|
||||
|
||||
L<http://clusterssh.sourceforge.net/>,
|
||||
C<ssh>,
|
||||
L<Tk::overview>,
|
||||
L<X11::Protocol>,
|
||||
C<perl>
|
||||
|
||||
=head1 CREDITS
|
||||
|
||||
A web site for comments, requests, bug reports and bug fixes/patches is
|
||||
available at L<http://clusterssh.sourceforge.net/>
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Duncan Ferguson, C<< <duncan_j_ferguson at yahoo.co.uk> >>
|
||||
|
||||
=head1 LICENSE AND COPYRIGHT
|
||||
|
||||
Copyright 1999-2010 Duncan Ferguson.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of either: the GNU General Public License as published
|
||||
by the Free Software Foundation; or the Artistic License.
|
||||
|
||||
See http://dev.perl.org/licenses/ for more information.
|
||||
|
||||
=cut
|
||||
|
||||
1;
|
1
bin/ctel
1
bin/ctel
|
@ -1 +0,0 @@
|
|||
cssh
|
47
bin_PL/_build_docs
Executable file
47
bin_PL/_build_docs
Executable file
|
@ -0,0 +1,47 @@
|
|||
#!/usr/bin/env perl
|
||||
use 5.008.004;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use FindBin qw($Bin $Script);
|
||||
use File::Basename;
|
||||
|
||||
my $bindir = "bin";
|
||||
|
||||
if ( !-d $bindir ) {
|
||||
mkdir $bindir || die "Could not mkdir $bindir: $!";
|
||||
}
|
||||
|
||||
print "Using perl binary: $^X", $/;
|
||||
print "Using perl version $^V", $/;
|
||||
|
||||
for my $dest (@ARGV) {
|
||||
my $source = $Bin . '/' . basename($dest);
|
||||
|
||||
next if ( $source =~ m/$Script/ );
|
||||
next if ( $source =~ m/\.x$/ );
|
||||
|
||||
print "Generating: $source", $/;
|
||||
|
||||
if ( -f $dest ) {
|
||||
chmod( 0755, $dest ) || die "Could not chmod $dest for removing: $!";
|
||||
}
|
||||
|
||||
open( my $sfh, '<', $source )
|
||||
|| die "Could not open $source for reading: $!";
|
||||
open( my $dfh, '>', $dest ) || die "Could not open $dest for writing: $!";
|
||||
print $dfh $_ while (<$sfh>);
|
||||
close($sfh);
|
||||
|
||||
if ( $source !~ m/clusterssh_bash_completion.dist/ ) {
|
||||
print $dfh "\n\n__END__\n\n";
|
||||
|
||||
my $pod = qx{ $^X $source --generate-pod };
|
||||
die "Failed to generate pod" if ($?);
|
||||
print $dfh $pod;
|
||||
}
|
||||
|
||||
close($dfh);
|
||||
|
||||
chmod( 0555, $dest ) || die "Could not chmod $dest: $!";
|
||||
}
|
25
bin_PL/ccon
Executable file
25
bin_PL/ccon
Executable file
|
@ -0,0 +1,25 @@
|
|||
#!/usr/bin/env perl
|
||||
use 5.008.004;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use FindBin;
|
||||
use lib $FindBin::Bin. '/../lib';
|
||||
use lib $FindBin::Bin. '/../lib/perl5';
|
||||
use App::ClusterSSH;
|
||||
|
||||
my $app = App::ClusterSSH->new();
|
||||
|
||||
#$app->options->add_common_ssh_options;
|
||||
#$app->options->add_common_session_options;
|
||||
|
||||
$app->add_option(
|
||||
spec => 'master|M=s',
|
||||
help => $app->loc(
|
||||
"The console client program polls master as the primary server, rather than the default set at compile time (typically ``console'')."
|
||||
),
|
||||
);
|
||||
|
||||
$app->run();
|
||||
|
||||
1;
|
70
bin_PL/clusterssh_bash_completion.dist
Normal file
70
bin_PL/clusterssh_bash_completion.dist
Normal file
|
@ -0,0 +1,70 @@
|
|||
# -*- mode: shell-script; sh-basic-offset: 8; indent-tabs-mode: t -*-
|
||||
# ex: ts=8 sw=8 noet filetype=sh
|
||||
#
|
||||
# cssh(1) completion by Aaron Spettl <aaron@spettl.de>, adapted from the
|
||||
# Debian GNU/Linux dput(1) completion by Roland Mas <lolando@debian.org>
|
||||
#
|
||||
# On Debian (and Debian based distributions) drop this file into
|
||||
# /etc/bash_completion.d
|
||||
# and source the /etc/bash_completion script - or just restart bash.
|
||||
|
||||
_cssh ()
|
||||
{
|
||||
local cur prev options paroptions clusters extra_cluster_file_line clusters_line extra_cluster_file
|
||||
|
||||
COMPREPLY=()
|
||||
cur=${COMP_WORDS[COMP_CWORD]}
|
||||
prev=${COMP_WORDS[COMP_CWORD-1]}
|
||||
|
||||
# all options understood by cssh
|
||||
options='-c --cluster-file -C --config-file --debug -e --evaluate \
|
||||
-g --tile -G --no-tile -h --help -H --man -l --username \
|
||||
-o --options -p --port -q --autoquit -Q --no-autoquit \
|
||||
-s --show-history -t --term-args -T --title \
|
||||
-u --output-config -v --version'
|
||||
|
||||
# find the extra cluster file line in the .clusterssh/config or, alternatively, /etc/csshrc
|
||||
extra_cluster_file_line="`grep '^[[:space:]]*extra_cluster_file' $HOME/.clusterssh/config 2> /dev/null`"
|
||||
[ -z "$extra_cluster_file_line" ] && extra_cluster_file_line="`grep '^[[:space:]]*extra_cluster_file' /etc/csshrc 2> /dev/null`"
|
||||
|
||||
# find the clusters line in the .csshrc or, alternatively, /etc/csshrc
|
||||
clusters_line="`grep '^[[:space:]]*clusters' $HOME/.clusterssh/config 2> /dev/null`"
|
||||
[ -z "$clusters_line" ] && clusters_line="`grep '^[[:space:]]*clusters' /etc/csshrc 2> /dev/null`"
|
||||
|
||||
# extract the location of the extra cluster file
|
||||
extra_cluster_file="`echo $extra_cluster_file_line | cut -f 2- -d '='`"
|
||||
[ -n "$extra_cluster_file" ] && extra_cluster_file="`eval echo $extra_cluster_file`"
|
||||
# TODO: don't use eval to expand ~ and $HOME
|
||||
|
||||
# get the names of all defined clusters
|
||||
clusters=$(
|
||||
{
|
||||
[ -n "$clusters_line" ] && echo "$clusters_line" | cut -f 2- -d '=' | tr "$IFS" "\n" || /bin/true
|
||||
[ -n "$extra_cluster_file" ] && sed -e 's/^\([a-z0-9.-]\+\).*$/\1/i' "$extra_cluster_file" 2> /dev/null || /bin/true
|
||||
sed -e 's/^\([a-z0-9.-]\+\).*$/\1/i' /etc/clusters 2> /dev/null || /bin/true
|
||||
sed -e 's/^\([a-z0-9.-]\+\).*$/\1/i' $HOME/.clusterssh/clusters 2> /dev/null || /bin/true
|
||||
} | sort -u)
|
||||
|
||||
# use options and clusters for tab completion, except there isn't yet
|
||||
# at least one character to filter by
|
||||
# reason: don't show options if the user types "cssh <tab><tab>"
|
||||
paroptions="$clusters"
|
||||
[ -n "$cur" ] && paroptions="$paroptions $options"
|
||||
|
||||
case $prev in
|
||||
--cluster-file|-c|--config-file|-C)
|
||||
COMPREPLY=( $( compgen -o filenames -G "$cur*" ) )
|
||||
;;
|
||||
*)
|
||||
COMPREPLY=()
|
||||
|
||||
# also use ssh hosts for tab completion if function _known_hosts is present
|
||||
[ "`type -t _known_hosts`" = "function" ] && _known_hosts -a
|
||||
|
||||
COMPREPLY=( "${COMPREPLY[@]}" $( compgen -W "$paroptions" | grep "^$cur") )
|
||||
;;
|
||||
esac
|
||||
|
||||
return 0
|
||||
} &&
|
||||
complete -F _cssh cssh crsh ctel
|
17
bin_PL/crsh
Executable file
17
bin_PL/crsh
Executable file
|
@ -0,0 +1,17 @@
|
|||
#!/usr/bin/env perl
|
||||
use 5.008.004;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use FindBin;
|
||||
use lib $FindBin::Bin. '/../lib';
|
||||
use lib $FindBin::Bin. '/../lib/perl5';
|
||||
use App::ClusterSSH;
|
||||
|
||||
my $app = App::ClusterSSH->new();
|
||||
|
||||
$app->options->add_common_ssh_options;
|
||||
$app->options->add_common_session_options;
|
||||
$app->run();
|
||||
|
||||
1;
|
2
bin/cscp → bin_PL/cscp.x
Executable file → Normal file
2
bin/cscp → bin_PL/cscp.x
Executable file → Normal file
|
@ -1,6 +1,6 @@
|
|||
#!/bin/sh
|
||||
|
||||
#LICENSE: Gnu GPL version 2
|
||||
#LICENSE: GNU GPL version 2
|
||||
#Author: JT Moree: moreejt@pcxperience.com
|
||||
#Copyright: Kahala Corp. 2006
|
||||
#Date: 20061213
|
17
bin_PL/csftp
Executable file
17
bin_PL/csftp
Executable file
|
@ -0,0 +1,17 @@
|
|||
#!/usr/bin/env perl
|
||||
use 5.008.004;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use FindBin;
|
||||
use lib $FindBin::Bin. '/../lib';
|
||||
use lib $FindBin::Bin. '/../lib/perl5';
|
||||
use App::ClusterSSH;
|
||||
|
||||
my $app = App::ClusterSSH->new();
|
||||
|
||||
$app->options->add_common_ssh_options;
|
||||
$app->options->add_common_session_options;
|
||||
$app->run();
|
||||
|
||||
1;
|
17
bin_PL/cssh
Executable file
17
bin_PL/cssh
Executable file
|
@ -0,0 +1,17 @@
|
|||
#!/usr/bin/env perl
|
||||
use 5.008.004;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use FindBin;
|
||||
use lib $FindBin::Bin. '/../lib';
|
||||
use lib $FindBin::Bin. '/../lib/perl5';
|
||||
use App::ClusterSSH;
|
||||
|
||||
my $app = App::ClusterSSH->new();
|
||||
|
||||
$app->options->add_common_ssh_options;
|
||||
$app->options->add_common_session_options;
|
||||
$app->run();
|
||||
|
||||
1;
|
13
bin_PL/ctel
Executable file
13
bin_PL/ctel
Executable file
|
@ -0,0 +1,13 @@
|
|||
#!/usr/bin/env perl
|
||||
use 5.008.004;
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use FindBin;
|
||||
use lib $FindBin::Bin. '/../lib';
|
||||
use lib $FindBin::Bin. '/../lib/perl5';
|
||||
use App::ClusterSSH;
|
||||
|
||||
my $app = App::ClusterSSH->new();
|
||||
|
||||
$app->run();
|
74
dist.ini
Normal file
74
dist.ini
Normal file
|
@ -0,0 +1,74 @@
|
|||
name = App-ClusterSSH
|
||||
author = Duncan Ferguson <duncan_j_ferguson@yahoo.co.uk>
|
||||
license = Perl_5
|
||||
copyright_holder = Duncan Ferguson
|
||||
copyright_year = 2018
|
||||
|
||||
[Git::Check]
|
||||
|
||||
[GatherDir]
|
||||
[MetaYAML]
|
||||
[ModuleBuild::Custom]
|
||||
mb_class = App::ClusterSSH:Build
|
||||
|
||||
[InstallGuide]
|
||||
[License]
|
||||
[PruneCruft]
|
||||
[PruneFiles]
|
||||
match = ^bin/
|
||||
match = \.bak$
|
||||
match = ^Build\.PL\.
|
||||
|
||||
[ManifestSkip]
|
||||
[Manifest]
|
||||
[TestRelease]
|
||||
[ConfirmRelease]
|
||||
[UploadToCPAN]
|
||||
|
||||
; for later
|
||||
;[Twitter]
|
||||
[EmailNotify]
|
||||
to = duncan_j_ferguson@yahoo.co.uk
|
||||
from = duncan_j_ferguson@yahoo.co.uk
|
||||
|
||||
[CheckChangeLog]
|
||||
|
||||
[PerlTidy]
|
||||
perltidyrc = t/perltidyrc
|
||||
|
||||
; Need to decide how to do this automatically at some point
|
||||
[VersionFromModule]
|
||||
;[Git::NextVersion]
|
||||
;[AutoVersion]
|
||||
[AutoPrereqs]
|
||||
[PkgVersion]
|
||||
[NextRelease]
|
||||
[Git::Commit]
|
||||
[Git::Tag]
|
||||
[Git::Push]
|
||||
|
||||
; optional prereqs - only used if they are installed
|
||||
[Prereqs / RuntimeRecommends]
|
||||
Sort::Naturally = 1.03
|
||||
|
||||
; Author prereqs
|
||||
; authordep Pod::Coverage::TrustPod
|
||||
; authordep Test::CPAN::Changes
|
||||
|
||||
[MetaResources]
|
||||
homepage = http://github.com/duncs/clusterssh/wiki
|
||||
bugtracker.web = https://github.com/duncs/clusterssh/issues
|
||||
repository.web = http://github.com/duncs/clusterssh
|
||||
repository.type = git
|
||||
; these two custom ones cause errors
|
||||
;Ci.web = https://travis-ci.org/duncs/clusterssh
|
||||
;Coverage.web = https://coveralls.io/github/duncs/clusterssh
|
||||
|
||||
[ExtraTests]
|
||||
; Disabled for the moment
|
||||
;[Test::Perl::Critic]
|
||||
[PodCoverageTests]
|
||||
[PodSyntaxTests]
|
||||
|
||||
[Run::BeforeBuild]
|
||||
run = bin_PL/cssh --generate-pod | pod2text > README
|
File diff suppressed because it is too large
Load diff
|
@ -1,24 +1,45 @@
|
|||
package App::ClusterSSH::Base;
|
||||
|
||||
use warnings;
|
||||
use strict;
|
||||
|
||||
package App::ClusterSSH::Base;
|
||||
|
||||
# ABSTRACT: App::ClusterSSH::Base - Base object provding utility functions
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
use base qw/ App::ClusterSSH::Base /;
|
||||
|
||||
# in object new method
|
||||
sub new {
|
||||
( $class, $arg_ref ) = @_;
|
||||
my $self = $class->SUPER::new($arg_ref);
|
||||
return $self;
|
||||
}
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Base object to provide some utility functions on objects - should not be
|
||||
used directly
|
||||
|
||||
=cut
|
||||
|
||||
use Carp;
|
||||
use App::ClusterSSH::L10N;
|
||||
|
||||
use Exception::Class (
|
||||
use Module::Load;
|
||||
|
||||
use Exception::Class 1.31 (
|
||||
'App::ClusterSSH::Exception',
|
||||
'App::ClusterSSH::Exception::Config' => {
|
||||
fields => 'unknown_config',
|
||||
},
|
||||
'App::ClusterSSH::Exception::Cluster',
|
||||
'App::ClusterSSH::Exception::LoadFile',
|
||||
'App::ClusterSSH::Exception::Helper',
|
||||
'App::ClusterSSH::Exception::Getopt',
|
||||
);
|
||||
|
||||
# Dont use SVN revision as it can cause problems
|
||||
use version;
|
||||
our $VERSION = version->new('0.02');
|
||||
|
||||
my $debug_level = 4;
|
||||
my $debug_level = $ENV{CLUSTERSSH_DEBUG} || 0;
|
||||
our $language = 'en';
|
||||
our $language_handle;
|
||||
our $app_configuration;
|
||||
|
@ -27,14 +48,13 @@ sub new {
|
|||
my ( $class, %args ) = @_;
|
||||
|
||||
my $config = {
|
||||
lang => 'en',
|
||||
debug => 0,
|
||||
lang => 'en',
|
||||
%args,
|
||||
};
|
||||
|
||||
my $self = bless $config, $class;
|
||||
|
||||
$self->set_debug_level( $config->{debug} );
|
||||
$self->set_debug_level( $config->{debug} ) if ( $config->{debug} );
|
||||
$self->set_lang( $config->{lang} );
|
||||
|
||||
$self->debug(
|
||||
|
@ -85,10 +105,7 @@ sub loc {
|
|||
|
||||
sub set_lang {
|
||||
my ( $self, $lang ) = @_;
|
||||
$language = $lang;
|
||||
if ($self) {
|
||||
$self->debug( 6, $self->loc( 'Setting language to "[_1]"', $lang ), );
|
||||
}
|
||||
$self->debug( 6, $self->loc( 'Setting language to "[_1]"', $lang ), );
|
||||
return $self;
|
||||
}
|
||||
|
||||
|
@ -113,7 +130,7 @@ sub debug_level {
|
|||
return $debug_level;
|
||||
}
|
||||
|
||||
sub output {
|
||||
sub stdout_output {
|
||||
my ( $self, @text ) = @_;
|
||||
print @text, $/;
|
||||
return $self;
|
||||
|
@ -122,7 +139,7 @@ sub output {
|
|||
sub debug {
|
||||
my ( $self, $level, @text ) = @_;
|
||||
if ( $level <= $debug_level ) {
|
||||
$self->output(@text);
|
||||
$self->stdout_output(@text);
|
||||
}
|
||||
return $self;
|
||||
}
|
||||
|
@ -144,9 +161,21 @@ sub config {
|
|||
);
|
||||
}
|
||||
|
||||
return $self->{parent}->{config}
|
||||
if $self->{parent}
|
||||
&& ref $self->{parent} eq "HASH"
|
||||
&& $self->{parent}->{config};
|
||||
|
||||
return $app_configuration;
|
||||
}
|
||||
|
||||
sub options {
|
||||
my ($self) = @_;
|
||||
return $self->{parent}->{options}
|
||||
if $self->{parent} && $self->{parent}->{options};
|
||||
return;
|
||||
}
|
||||
|
||||
sub set_config {
|
||||
my ( $self, $config ) = @_;
|
||||
|
||||
|
@ -184,10 +213,10 @@ sub load_file {
|
|||
);
|
||||
}
|
||||
|
||||
if ( !$args{type} || $args{type} !~ m/cluster|config/ ) {
|
||||
if ( !$args{type} ) {
|
||||
croak(
|
||||
App::ClusterSSH::Exception->throw(
|
||||
error => '"type" arg invalid'
|
||||
error => '"type" arg not passed'
|
||||
)
|
||||
);
|
||||
}
|
||||
|
@ -267,29 +296,38 @@ sub load_file {
|
|||
return %results;
|
||||
}
|
||||
|
||||
1;
|
||||
sub parent {
|
||||
my ($self) = @_;
|
||||
return $self->{parent};
|
||||
}
|
||||
|
||||
=pod
|
||||
sub sort {
|
||||
my $self = shift;
|
||||
|
||||
=head1 NAME
|
||||
# if the user has asked for natural sorting we need to include an extra
|
||||
# module
|
||||
my $config = $self->config();
|
||||
|
||||
App::ClusterSSH::Base - Base object provding utility functions
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
use base qw/ App::ClusterSSH::Base /;
|
||||
|
||||
# in object new method
|
||||
sub new {
|
||||
( $class, $arg_ref ) = @_;
|
||||
my $self = $class->SUPER::new($arg_ref);
|
||||
return $self;
|
||||
# Make sure the configuration object has been set correctly before
|
||||
# referencing anything
|
||||
if ( ref $config eq "HASH" && $config->{'use_natural_sort'} ) {
|
||||
eval { Module::Load::load('Sort::Naturally'); };
|
||||
if ($@) {
|
||||
warn(
|
||||
"natural sorting requested but unable to load Sort::Naturally: $@\n"
|
||||
);
|
||||
}
|
||||
else {
|
||||
my $sort = sub { Sort::Naturally::nsort(@_) };
|
||||
return $sort;
|
||||
}
|
||||
}
|
||||
|
||||
=head1 DESCRIPTION
|
||||
my $sort = sub { sort @_ };
|
||||
return $sort;
|
||||
}
|
||||
|
||||
Base object to provide some utility functions on objects - should not be
|
||||
used directly
|
||||
1;
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
|
@ -331,10 +369,19 @@ Using the App::ClusterSSH/L10N/{lang}.pm module convert the given text to
|
|||
appropriate language. See L<App::ClusterSSH::L10N> for more details. Essentially
|
||||
a wrapper to maketext in Locale::Maketext
|
||||
|
||||
=item $obj->output(@);
|
||||
=item $obj->stdout_output(@);
|
||||
|
||||
Output text on STDOUT.
|
||||
|
||||
=item $obj->parent;
|
||||
|
||||
Returned the object that is the parent of this one, if it was set when the
|
||||
object was created
|
||||
|
||||
=item %obj->options;
|
||||
|
||||
Accessor to configured options, if it is set up by this point
|
||||
|
||||
=item $obj->exit;
|
||||
|
||||
Stub to allow program to exit neatly from wherever in the code
|
||||
|
@ -348,27 +395,14 @@ hasnt been called
|
|||
|
||||
Set the config to the given value - croaks if has already been called
|
||||
|
||||
=item $sort = $obj->sort
|
||||
|
||||
Code reference used to sort lists; if configured (and installed) use
|
||||
Sort;:Naturally, else use perl sort
|
||||
|
||||
=item %results = $obj->load_file( filename => '/path/to/file', type => '(cluster|config}' )
|
||||
|
||||
Load in the specified file and return a hash, parsing the file depending on
|
||||
wther it is a config file (key = value) or cluster file (key value)
|
||||
|
||||
=back
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Duncan Ferguson, C<< <duncan_j_ferguson at yahoo.co.uk> >>
|
||||
|
||||
=head1 LICENSE AND COPYRIGHT
|
||||
|
||||
Copyright 1999-2010 Duncan Ferguson.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of either: the GNU General Public License as published
|
||||
by the Free Software Foundation; or the Artistic License.
|
||||
|
||||
See http://dev.perl.org/licenses/ for more information.
|
||||
|
||||
=cut
|
||||
|
||||
1;
|
||||
|
|
|
@ -1,16 +1,24 @@
|
|||
package App::ClusterSSH::Cluster;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use version;
|
||||
our $VERSION = version->new('0.01');
|
||||
package App::ClusterSSH::Cluster;
|
||||
|
||||
# ABSTRACT: App::ClusterSSH::Cluster - Object representing cluster configuration
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Object representing application configuration
|
||||
|
||||
=cut
|
||||
|
||||
use Carp;
|
||||
use Try::Tiny;
|
||||
use Try::Tiny 0.28;
|
||||
use English qw( -no_match_vars );
|
||||
|
||||
use base qw/ App::ClusterSSH::Base /;
|
||||
use App::ClusterSSH::Range;
|
||||
|
||||
our $master_object_ref;
|
||||
|
||||
|
@ -48,14 +56,40 @@ sub get_tag_entries {
|
|||
return $self;
|
||||
}
|
||||
|
||||
sub list_external_clusters {
|
||||
my ( $self, ) = @_;
|
||||
|
||||
my @list = $self->_run_external_clusters('-L');
|
||||
return wantarray
|
||||
? sort @list
|
||||
: scalar @list;
|
||||
}
|
||||
|
||||
sub get_external_clusters {
|
||||
my ( $self, $external_command, @tags ) = @_;
|
||||
my ( $self, @tags ) = @_;
|
||||
|
||||
return $self->_run_external_clusters(@tags);
|
||||
}
|
||||
|
||||
sub _run_external_clusters {
|
||||
my ( $self, @args ) = @_;
|
||||
|
||||
my $external_command = $self->parent->config->{external_cluster_command};
|
||||
|
||||
if ( !$external_command || !-x $external_command ) {
|
||||
$self->debug(
|
||||
1,
|
||||
'Cannot run external cluster command: ',
|
||||
$external_command || ''
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
$self->debug( 3, 'Running tags through external command' );
|
||||
$self->debug( 4, 'External command: ', $external_command );
|
||||
$self->debug( 3, 'Tags: ', join( ',', @tags ) );
|
||||
$self->debug( 3, 'Args ', join( ',', @args ) );
|
||||
|
||||
my $command = "$external_command @tags";
|
||||
my $command = "$external_command @args";
|
||||
|
||||
$self->debug( 3, 'Running ', $command );
|
||||
|
||||
|
@ -88,8 +122,37 @@ sub get_external_clusters {
|
|||
return @results;
|
||||
}
|
||||
|
||||
sub expand_filename {
|
||||
my ( $self, $filename ) = @_;
|
||||
my $home;
|
||||
|
||||
# try to determine the home directory
|
||||
if ( !defined( $home = $ENV{'HOME'} ) ) {
|
||||
$home = ( getpwuid($>) )[5];
|
||||
}
|
||||
if ( !defined($home) ) {
|
||||
$self->debug( 3, 'No home found so leaving filename ',
|
||||
$filename, ' unexpanded' );
|
||||
return $filename;
|
||||
}
|
||||
$self->debug( 4, 'Using ', $home, ' as home directory' );
|
||||
|
||||
# expand ~ or $HOME
|
||||
my $new_name = $filename;
|
||||
$new_name =~ s!^~/!$home/!g;
|
||||
$new_name =~ s!^\$HOME/!$home/!g;
|
||||
|
||||
$self->debug( 2, 'Expanding ', $filename, ' to ', $new_name )
|
||||
unless ( $filename eq $new_name );
|
||||
|
||||
return $new_name;
|
||||
}
|
||||
|
||||
sub read_tag_file {
|
||||
my ( $self, $filename ) = @_;
|
||||
|
||||
$filename = $self->expand_filename($filename);
|
||||
|
||||
$self->debug( 2, 'Reading tags from file ', $filename );
|
||||
if ( -f $filename ) {
|
||||
my %hosts
|
||||
|
@ -107,6 +170,9 @@ sub read_tag_file {
|
|||
|
||||
sub read_cluster_file {
|
||||
my ( $self, $filename ) = @_;
|
||||
|
||||
$filename = $self->expand_filename($filename);
|
||||
|
||||
$self->debug( 2, 'Reading clusters from file ', $filename );
|
||||
|
||||
if ( -f $filename ) {
|
||||
|
@ -127,6 +193,8 @@ sub register_host {
|
|||
my ( $self, $node, @tags ) = @_;
|
||||
$self->debug( 2, "Registering node $node on tags:", join( ' ', @tags ) );
|
||||
|
||||
@tags = $self->expand_glob( 'node', $node, @tags );
|
||||
|
||||
foreach my $tag (@tags) {
|
||||
if ( $self->{tags}->{$tag} ) {
|
||||
$self->{tags}->{$tag}
|
||||
|
@ -144,6 +212,11 @@ sub register_host {
|
|||
sub register_tag {
|
||||
my ( $self, $tag, @nodes ) = @_;
|
||||
|
||||
#warn "b4 nodes=@nodes";
|
||||
@nodes = $self->expand_glob( 'tag', $tag, @nodes );
|
||||
|
||||
#warn "af nodes=@nodes";
|
||||
|
||||
$self->debug( 2, "Registering tag $tag: ", join( ' ', @nodes ) );
|
||||
|
||||
$self->{tags}->{$tag} = \@nodes;
|
||||
|
@ -151,6 +224,35 @@ sub register_tag {
|
|||
return $self;
|
||||
}
|
||||
|
||||
sub expand_glob {
|
||||
my ( $self, $type, $name, @items ) = @_;
|
||||
|
||||
my @expanded;
|
||||
my $range = App::ClusterSSH::Range->new();
|
||||
|
||||
# skip expanding anything that appears to have nasty metachars
|
||||
if ( !grep {m/[\`\!\$;]/} @items ) {
|
||||
|
||||
$self->debug( 4, "Non-expanded: @items" );
|
||||
|
||||
@items = $range->expand(@items);
|
||||
|
||||
# run glob over anything left incase there are numeric and textual ranges
|
||||
@expanded = map { glob $_ } @items;
|
||||
$self->debug( 4, "Final expansion: @expanded" );
|
||||
}
|
||||
else {
|
||||
warn(
|
||||
$self->loc(
|
||||
"Bad characters picked up in [_1] '[_2]': [_3]",
|
||||
$type, $name, join( ' ', @items )
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
return @expanded;
|
||||
}
|
||||
|
||||
sub get_tag {
|
||||
my ( $self, $tag ) = @_;
|
||||
|
||||
|
@ -161,8 +263,7 @@ sub get_tag {
|
|||
join( ' ', sort @{ $self->{tags}->{$tag} } )
|
||||
);
|
||||
|
||||
return
|
||||
wantarray
|
||||
return wantarray
|
||||
? sort @{ $self->{tags}->{$tag} }
|
||||
: scalar @{ $self->{tags}->{$tag} };
|
||||
}
|
||||
|
@ -173,7 +274,9 @@ sub get_tag {
|
|||
|
||||
sub list_tags {
|
||||
my ($self) = @_;
|
||||
return sort keys( %{ $self->{tags} } );
|
||||
return wantarray
|
||||
? sort keys( %{ $self->{tags} } )
|
||||
: scalar keys( %{ $self->{tags} } );
|
||||
}
|
||||
|
||||
sub dump_tags {
|
||||
|
@ -191,18 +294,6 @@ sub dump_tags {
|
|||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
App::ClusterSSH::Cluster - Object representing cluster configuration
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Object representing application configuration
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
=over 4
|
||||
|
@ -216,9 +307,13 @@ Create a new object. Object should be common across all invocations.
|
|||
Read in /etc/clusters, $HOME/.clusterssh/clusters and any other given
|
||||
file name and register the tags found.
|
||||
|
||||
=item @resolved_tags=get_external_clusters($path_to_binary, @tags)
|
||||
=item @external_tags=list_external_clusters()
|
||||
|
||||
Define and use an external script to resolve tags into hostnames.
|
||||
Call an external script suing C<-L> to list available tags
|
||||
|
||||
=item @resolved_tags=get_external_clusters(@tags)
|
||||
|
||||
Use an external script to resolve C<@tags> into hostnames.
|
||||
|
||||
=item $cluster->get_tag_entries($filename);
|
||||
|
||||
|
@ -229,6 +324,10 @@ file name and register the tags found.
|
|||
|
||||
Read in the given cluster file and register the tags found
|
||||
|
||||
=item $cluster->expand_filename($filename);
|
||||
|
||||
Expand ~ or $HOME in a filename
|
||||
|
||||
=item $cluster->read_tag_file($filename);
|
||||
|
||||
Read in the given tag file and register the tags found
|
||||
|
@ -256,22 +355,8 @@ Return an array of all available tag names
|
|||
|
||||
Returns a hash of all tag data.
|
||||
|
||||
=item @tags = $cluster->expand_glob( $type, $name, @items );
|
||||
|
||||
Use shell expansion against each item in @items, where $type is either 'node', or 'tag' and $name is the node or tag name. These attributes are presented to the user in the event of an issue with the expanion to track down the source.
|
||||
|
||||
=back
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Duncan Ferguson, C<< <duncan_j_ferguson at yahoo.co.uk> >>
|
||||
|
||||
=head1 LICENSE AND COPYRIGHT
|
||||
|
||||
Copyright 1999-2010 Duncan Ferguson.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of either: the GNU General Public License as published
|
||||
by the Free Software Foundation; or the Artistic License.
|
||||
|
||||
See http://dev.perl.org/licenses/ for more information.
|
||||
|
||||
=cut
|
||||
|
||||
1;
|
||||
|
|
|
@ -1,10 +1,17 @@
|
|||
package App::ClusterSSH::Config;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use version;
|
||||
our $VERSION = version->new('0.02');
|
||||
package App::ClusterSSH::Config;
|
||||
|
||||
# ABSTRACT: ClusterSSH::Config - Object representing application configuration
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Object representing application configuration
|
||||
|
||||
=cut
|
||||
|
||||
use Carp;
|
||||
use Try::Tiny;
|
||||
|
@ -17,7 +24,7 @@ use App::ClusterSSH::Cluster;
|
|||
|
||||
my $clusters;
|
||||
my %old_clusters;
|
||||
my @app_specific = (qw/ command title comms method /);
|
||||
my @app_specific = (qw/ command title comms method parent /);
|
||||
|
||||
# list of config items to not write out when writing the default config
|
||||
my @ignore_default_config = (qw/ user /);
|
||||
|
@ -33,7 +40,7 @@ my %default_config = (
|
|||
terminal_size => "80x24",
|
||||
|
||||
use_hotkeys => "yes",
|
||||
key_quit => "Control-q",
|
||||
key_quit => "Alt-q",
|
||||
key_addhost => "Control-Shift-plus",
|
||||
key_clientname => "Alt-n",
|
||||
key_history => "Alt-h",
|
||||
|
@ -42,9 +49,14 @@ 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,
|
||||
use_natural_sort => 0,
|
||||
window_tiling => "yes",
|
||||
window_tiling_direction => "right",
|
||||
console_position => "",
|
||||
|
@ -70,9 +82,14 @@ my %default_config = (
|
|||
telnet_args => "",
|
||||
ssh => 'ssh',
|
||||
ssh_args => "",
|
||||
sftp => 'sftp',
|
||||
sftp_args => "",
|
||||
|
||||
extra_tag_file => '',
|
||||
extra_cluster_file => '',
|
||||
external_cluster_command => '',
|
||||
external_command_mode => '0600',
|
||||
external_command_pipe => '',
|
||||
|
||||
unmap_on_redraw => "no", # Debian #329440
|
||||
|
||||
|
@ -81,6 +98,9 @@ my %default_config = (
|
|||
history_height => 10,
|
||||
|
||||
command => q{},
|
||||
command_pre => q{},
|
||||
command_post => q{},
|
||||
hide_menu => 0,
|
||||
max_host_menu_items => 30,
|
||||
|
||||
macros_enabled => 'yes',
|
||||
|
@ -89,17 +109,35 @@ 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 => '',
|
||||
hostname_override => '',
|
||||
|
||||
max_addhost_menu_cluster_items => 6,
|
||||
menu_send_autotearoff => 0,
|
||||
menu_host_autotearoff => 0,
|
||||
|
||||
unique_servers => 0,
|
||||
use_all_a_records => 0,
|
||||
|
||||
send_menu_xml_file => $ENV{HOME} . '/.csshrc_send_menu',
|
||||
send_menu_xml_file => $ENV{HOME} . '/.clusterssh/send_menu',
|
||||
|
||||
auto_wm_decoration_offsets => "no", # Debian #842965
|
||||
|
||||
# don't set username here as takes precendence over ssh config
|
||||
user => '',
|
||||
rows => -1,
|
||||
cols => -1,
|
||||
|
||||
fillscreen => "no",
|
||||
|
||||
);
|
||||
|
||||
sub new {
|
||||
|
@ -112,9 +150,10 @@ sub new {
|
|||
$comms = 'telnet' if ( $comms eq 'tel' );
|
||||
$comms = 'console' if ( $comms eq 'con' );
|
||||
$comms = 'ssh' if ( $comms eq 'lusterssh' );
|
||||
$comms = 'sftp' if ( $comms eq 'sftp' );
|
||||
|
||||
# list of allowed comms methods
|
||||
if ( 'ssh rsh telnet console' !~ m/\b$comms\b/ ) {
|
||||
if ( 'ssh rsh telnet sftp console' !~ m/\b$comms\b/ ) {
|
||||
$self->{comms} = 'ssh';
|
||||
}
|
||||
else {
|
||||
|
@ -179,12 +218,14 @@ sub validate_args {
|
|||
);
|
||||
}
|
||||
|
||||
# # Don't search for the path to the binary - assume it is on the path
|
||||
# # or defined correctly in the config.
|
||||
# if( !-e $self->{ $self->{comms} } )
|
||||
# {
|
||||
# $self->{ $self->{comms} } = $self->find_binary( $self->{comms} );
|
||||
# }
|
||||
# check the terminal has been found correctly
|
||||
# looking for the terminal should not be fatal
|
||||
if ( !-e $self->{terminal} ) {
|
||||
eval { $self->{terminal} = $self->find_binary( $self->{terminal} ); };
|
||||
if ($@) {
|
||||
warn $@->message;
|
||||
}
|
||||
}
|
||||
|
||||
return $self;
|
||||
}
|
||||
|
@ -254,6 +295,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 {
|
||||
|
@ -265,7 +315,7 @@ sub load_configs {
|
|||
$ENV{HOME} . '/.clusterssh/config',
|
||||
)
|
||||
{
|
||||
$self->parse_config_file($config) if ( -e $config );
|
||||
$self->parse_config_file($config) if ( -e $config && !-d _ );
|
||||
}
|
||||
|
||||
# write out default config file if necesasry
|
||||
|
@ -280,10 +330,22 @@ sub load_configs {
|
|||
# relative to config directory
|
||||
for my $config (@configs) {
|
||||
next unless ($config); # can be null when passed from Getopt::Long
|
||||
$self->parse_config_file($config) if ( -e $config );
|
||||
$self->parse_config_file($config) if ( -e $config && !-d _ );
|
||||
|
||||
my $file = $ENV{HOME} . '/.clusterssh/config_' . $config;
|
||||
$self->parse_config_file($file) if ( -e $file );
|
||||
$self->parse_config_file($file) if ( -e $file && !-d _ );
|
||||
}
|
||||
|
||||
# Override confuration via environment variable using cssh_ prefix
|
||||
# eg: terminal_size => cssh_terminal_size
|
||||
foreach my $config_key ( sort( keys(%default_config) ) ) {
|
||||
my $env_config_key = "cssh_" . $config_key;
|
||||
if ( exists $ENV{ uc($env_config_key) } ) {
|
||||
$env_config_key = uc($env_config_key);
|
||||
}
|
||||
if ( exists $ENV{$env_config_key} ) {
|
||||
$self->{$config_key} = $ENV{$env_config_key};
|
||||
}
|
||||
}
|
||||
|
||||
return $self;
|
||||
|
@ -387,6 +449,25 @@ sub write_user_config_file {
|
|||
return $self;
|
||||
}
|
||||
|
||||
# search given directories for the given file
|
||||
sub search_dirs {
|
||||
my ( $self, $file, @directories ) = @_;
|
||||
|
||||
my $path;
|
||||
|
||||
foreach my $dir (@directories) {
|
||||
$self->debug( 3, "Looking for $file in $dir" );
|
||||
|
||||
if ( -f $dir . '/' . $file && -x $dir . '/' . $file ) {
|
||||
$path = $dir . '/' . $file;
|
||||
$self->debug( 2, "Found at $path" );
|
||||
last;
|
||||
}
|
||||
}
|
||||
|
||||
return $path;
|
||||
}
|
||||
|
||||
# could use File::Which for some of this but we also search a few other places
|
||||
# just in case $PATH isnt set up right
|
||||
sub find_binary {
|
||||
|
@ -405,39 +486,39 @@ sub find_binary {
|
|||
# if not found, strip the path and look again
|
||||
if ( $binary =~ m!^/! ) {
|
||||
if ( -f $binary ) {
|
||||
$self->debug( 2, "$binary already fully qualified" );
|
||||
$self->debug( 2, "Already have full path to in $binary" );
|
||||
return $binary;
|
||||
}
|
||||
else {
|
||||
$self->debug( 2, "$binary not found - re-searching" );
|
||||
$self->debug( 2, "Full path for $binary incorrect; searching" );
|
||||
$binary =~ s!^.*/!!;
|
||||
}
|
||||
}
|
||||
|
||||
my $path;
|
||||
if ( !-x $binary || substr( $binary, 0, 1 ) ne '/' ) {
|
||||
$path = $self->search_dirs( $binary, split( /:/, $ENV{PATH} ) );
|
||||
|
||||
foreach (
|
||||
split( /:/, $ENV{PATH} ), qw!
|
||||
/bin
|
||||
/sbin
|
||||
/usr/sbin
|
||||
/usr/bin
|
||||
/usr/local/bin
|
||||
/usr/local/sbin
|
||||
/opt/local/bin
|
||||
/opt/local/sbin
|
||||
!
|
||||
)
|
||||
{
|
||||
$self->debug( 3, "Looking in $_" );
|
||||
|
||||
if ( -f $_ . '/' . $binary && -x $_ . '/' . $binary ) {
|
||||
$path = $_ . '/' . $binary;
|
||||
$self->debug( 2, "Found at $path" );
|
||||
last;
|
||||
}
|
||||
# if it is on $PATH then no need to qualitfy the path to it
|
||||
# keep it as it is
|
||||
if ($path) {
|
||||
return $binary;
|
||||
}
|
||||
else {
|
||||
$path = $self->search_dirs(
|
||||
$binary, qw!
|
||||
/bin
|
||||
/sbin
|
||||
/usr/sbin
|
||||
/usr/bin
|
||||
/usr/local/bin
|
||||
/usr/local/sbin
|
||||
/opt/local/bin
|
||||
/opt/local/sbin
|
||||
!
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
$self->debug( 2, "Already configured OK" );
|
||||
|
@ -463,7 +544,7 @@ sub dump {
|
|||
my ( $self, $no_exit, ) = @_;
|
||||
|
||||
$self->debug( 3, 'Dumping config to STDOUT' );
|
||||
print( '# Configuration dump produced by "cssh -u"', $/ );
|
||||
print( '# Configuration dump produced by "cssh -d"', $/ );
|
||||
|
||||
foreach my $key ( sort keys %$self ) {
|
||||
my $comment = '';
|
||||
|
@ -489,18 +570,6 @@ sub dump {
|
|||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
ClusterSSH::Config - Object representing application configuration
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Object representing application configuration
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
=over 4
|
||||
|
@ -517,6 +586,10 @@ Read in configuration from given filename
|
|||
|
||||
Validate and apply all configuration loaded at this point
|
||||
|
||||
=item $path = $config->search_dirs('<name>', @seaarch_directories);
|
||||
|
||||
Search the given directories for the name given. Return undef if not found.
|
||||
|
||||
=item $path = $config->find_binary('<name>');
|
||||
|
||||
Locate the binary <name> and return the full path. Doesn't just search
|
||||
|
@ -537,21 +610,3 @@ are loaded).
|
|||
Write currently defined configuration to STDOUT
|
||||
|
||||
=back
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Duncan Ferguson, C<< <duncan_j_ferguson at yahoo.co.uk> >>
|
||||
|
||||
=head1 LICENSE AND COPYRIGHT
|
||||
|
||||
Copyright 1999-2010 Duncan Ferguson.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of either: the GNU General Public License as published
|
||||
by the Free Software Foundation; or the Artistic License.
|
||||
|
||||
See http://dev.perl.org/licenses/ for more information.
|
||||
|
||||
=cut
|
||||
|
||||
1;
|
||||
|
|
1249
lib/App/ClusterSSH/Getopt.pm
Normal file
1249
lib/App/ClusterSSH/Getopt.pm
Normal file
File diff suppressed because it is too large
Load diff
|
@ -1,10 +1,17 @@
|
|||
package App::ClusterSSH::Helper;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use version;
|
||||
our $VERSION = version->new('0.02');
|
||||
package App::ClusterSSH::Helper;
|
||||
|
||||
# ABSTRACT: ClusterSSH::Helper - Object representing helper script
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Object representing application configuration
|
||||
|
||||
=cut
|
||||
|
||||
use Carp;
|
||||
use Try::Tiny;
|
||||
|
@ -22,6 +29,31 @@ sub new {
|
|||
sub script {
|
||||
my ( $self, $config ) = @_;
|
||||
|
||||
if ( !defined $config
|
||||
|| !ref $config
|
||||
|| ref $config ne "App::ClusterSSH::Config" )
|
||||
{
|
||||
croak(
|
||||
App::ClusterSSH::Exception::Helper->throw(
|
||||
error => 'No configuration provided or in wrong format',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
foreach my $arg ( "comms", $config->{comms}, $config->{comms} . '_args',
|
||||
'command', 'auto_close' )
|
||||
{
|
||||
if ( !defined $config->{$arg} ) {
|
||||
croak(
|
||||
App::ClusterSSH::Exception::Helper->throw(
|
||||
error => "Config '$arg' not provided",
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
my $command_pre = $config->{command_pre} || q{};
|
||||
my $command_post = $config->{command_post} || q{};
|
||||
my $comms = $config->{ $config->{comms} };
|
||||
my $comms_args = $config->{ $config->{comms} . '_args' };
|
||||
my $config_command = $config->{command};
|
||||
|
@ -33,66 +65,15 @@ sub script {
|
|||
: "echo Press RETURN to continue; read IGNORE"
|
||||
; # : "sleep $autoclose";
|
||||
|
||||
# # P = pipe file
|
||||
# # s = server
|
||||
# # u = username
|
||||
# # p = port
|
||||
# # m = ccon master
|
||||
# # c = comms command
|
||||
# # a = command args
|
||||
# # C = command to run
|
||||
# my $lelehelper_script = q{
|
||||
# use strict;
|
||||
# use warnings;
|
||||
# use Getopt::Std;
|
||||
# my %opts;
|
||||
# getopts('PsupmcaC', \%opts);
|
||||
# my $command="$opts{c} $opts{a}";
|
||||
# open(PIPE, ">", $opts{P}) or die("Failed to open pipe: $!\n");
|
||||
# print PIPE "$$:$ENV{WINDOWID}"
|
||||
# or die("Failed to write to pipe: $!\\n");
|
||||
# close(PIPE) or die("Failed to close pipe: $!\\n");
|
||||
# if($opts{s} =~ m/==$/)
|
||||
# {
|
||||
# $opts{s} =~ s/==$//;
|
||||
# warn("\nWARNING: failed to resolve IP address for $opts{s}.\n\n");
|
||||
# sleep 5;
|
||||
# }
|
||||
# if($opts{m}) {
|
||||
# unless("$comms" ne "console") {
|
||||
# $opts{m} = $opts{m} ? "-M $opts{m} " : "";
|
||||
# $opts{c} .= $opts{m};
|
||||
# }
|
||||
# }
|
||||
# if($opts{u}) {
|
||||
# unless("$comms" eq "telnet") {
|
||||
# $opts{u} = $opts{u} ? "-l $opts{u} " : "";
|
||||
# $opts{c} .= $opts{u};
|
||||
# }
|
||||
# }
|
||||
# if("$comms" eq "telnet") {
|
||||
# $command .= "$opts{s} $opts{p}";
|
||||
# } else {
|
||||
# if ($opts{p}) {
|
||||
# $opts{c} .= "-p $opts{p} $opts{s}";
|
||||
# } else {
|
||||
# $opts{c} .= "$opts{s}";
|
||||
# }
|
||||
# }
|
||||
# #$command .= " $command || sleep 5";
|
||||
# warn("Running:$command\n"); # for debug purposes
|
||||
# exec($command);
|
||||
# };
|
||||
|
||||
my $script = <<" HERE";
|
||||
my \$pipe=shift;
|
||||
my \$svr=shift;
|
||||
my \$user=shift;
|
||||
my \$port=shift;
|
||||
my \$mstr=shift;
|
||||
my \$command="$comms $comms_args ";
|
||||
my \$command="$command_pre $comms $comms_args ";
|
||||
open(PIPE, ">", \$pipe) or die("Failed to open pipe: \$!\\n");
|
||||
print PIPE "\$\$:\$ENV{WINDOWID}"
|
||||
print PIPE "\$\$:\$ENV{WINDOWID}"
|
||||
or die("Failed to write to pipe: $!\\n");
|
||||
close(PIPE) or die("Failed to close pipe: $!\\n");
|
||||
if(\$svr =~ m/==\$/)
|
||||
|
@ -126,8 +107,10 @@ sub script {
|
|||
if("$config_command") {
|
||||
\$command .= " \\\"$config_command\\\"";
|
||||
}
|
||||
\$command .= "$command_post";
|
||||
\$command .= " ; $postcommand";
|
||||
warn("Running:\$command\\n"); # for debug purposes
|
||||
# provide some info for debugging purposes
|
||||
warn("Running: \$command\\n");
|
||||
exec(\$command);
|
||||
HERE
|
||||
|
||||
|
@ -147,18 +130,6 @@ sub script {
|
|||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
ClusterSSH::Helper - Object representing helper script
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Object representing application configuration
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
=over 4
|
||||
|
@ -172,21 +143,3 @@ Create a new helper object.
|
|||
Return the helper script
|
||||
|
||||
=back
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Duncan Ferguson, C<< <duncan_j_ferguson at yahoo.co.uk> >>
|
||||
|
||||
=head1 LICENSE AND COPYRIGHT
|
||||
|
||||
Copyright 1999-2010 Duncan Ferguson.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of either: the GNU General Public License as published
|
||||
by the Free Software Foundation; or the Artistic License.
|
||||
|
||||
See http://dev.perl.org/licenses/ for more information.
|
||||
|
||||
=cut
|
||||
|
||||
1;
|
||||
|
|
|
@ -1,12 +1,28 @@
|
|||
package App::ClusterSSH::Host;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use version;
|
||||
our $VERSION = version->new('0.03');
|
||||
package App::ClusterSSH::Host;
|
||||
|
||||
# ABSTRACT: ClusterSSH::Host - Object representing a host.
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
use ClusterSSH::Host;
|
||||
|
||||
my $host = ClusterSSH::Host->new({
|
||||
hostname => 'hostname',
|
||||
});
|
||||
my $host = ClusterSSH::Host->parse_host_string('username@hostname:1234');
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Object representing a host. Include details to contact the host such as
|
||||
hostname/ipaddress, username and port.
|
||||
|
||||
=cut
|
||||
|
||||
use Carp;
|
||||
use Net::hostent;
|
||||
|
||||
use base qw/ App::ClusterSSH::Base /;
|
||||
|
||||
|
@ -25,7 +41,7 @@ sub new {
|
|||
}
|
||||
|
||||
# remove any keys undef values - must be a better way...
|
||||
foreach my $remove (qw/ port username /) {
|
||||
foreach my $remove (qw/ port username geometry /) {
|
||||
if ( !$args{$remove} && grep {/^$remove$/} keys(%args) ) {
|
||||
delete( $args{$remove} );
|
||||
}
|
||||
|
@ -36,33 +52,42 @@ sub new {
|
|||
|
||||
# load in ssh hostname for later use
|
||||
if ( !%ssh_hostname_for || !$ssh_configs_read{ $self->{ssh_config} } ) {
|
||||
$ssh_configs_read{ $self->{ssh_config} } = 1;
|
||||
if ( open( my $ssh_config_fh, '<', $self->{ssh_config} ) ) {
|
||||
while ( my $line = <$ssh_config_fh> ) {
|
||||
chomp $line;
|
||||
next unless ( $line =~ m/^\s*host\s+(.*)/i );
|
||||
$self->read_ssh_file( $self->{ssh_config} );
|
||||
|
||||
# account for multiple declarations of hosts
|
||||
$ssh_hostname_for{$_} = 1 foreach ( split( /\s+/, $1 ) );
|
||||
}
|
||||
close($ssh_config_fh);
|
||||
|
||||
$self->debug( 5, 'Have the following ssh hostnames' );
|
||||
$self->debug( 5, ' "', $_, '"' )
|
||||
foreach ( sort keys %ssh_hostname_for );
|
||||
}
|
||||
else {
|
||||
$self->debug( 3, 'Unable to read ',
|
||||
$self->{ssh_config}, ': ', $!, $/ );
|
||||
}
|
||||
$self->debug( 5, 'Have the following ssh hostnames' );
|
||||
$self->debug( 5, ' "', $_, '"' )
|
||||
foreach ( sort keys %ssh_hostname_for );
|
||||
}
|
||||
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub get_givenname {
|
||||
my ($self) = @_;
|
||||
return $self->{hostname};
|
||||
sub read_ssh_file($$) {
|
||||
my ($self) = shift;
|
||||
my ($filename) = glob(shift);
|
||||
$self->debug( 3, 'Reading SSH file: ', $filename );
|
||||
|
||||
$ssh_configs_read{$filename} = 1;
|
||||
|
||||
if ( open( my $ssh_config_fh, '<', $filename ) ) {
|
||||
while ( my $line = <$ssh_config_fh> ) {
|
||||
chomp $line;
|
||||
|
||||
if ( $line =~ /^\s*include\s+(.+)/i ) {
|
||||
$self->read_ssh_file($1);
|
||||
next;
|
||||
}
|
||||
|
||||
next unless ( $line =~ m/^\s*host\s+(.*)/i );
|
||||
|
||||
# account for multiple declarations of hosts
|
||||
$ssh_hostname_for{$_} = 1 foreach ( split( /\s+/, $1 ) );
|
||||
}
|
||||
close($ssh_config_fh);
|
||||
}
|
||||
else {
|
||||
$self->debug( 3, 'Unable to read ', $filename, ': ', $!, $/ );
|
||||
}
|
||||
}
|
||||
|
||||
sub get_hostname {
|
||||
|
@ -75,6 +100,19 @@ sub get_username {
|
|||
return $self->{username} || q{};
|
||||
}
|
||||
|
||||
sub get_type {
|
||||
my ($self) = @_;
|
||||
if ( $self->check_ssh_hostname ) {
|
||||
return 'ssh_alias';
|
||||
}
|
||||
return $self->{type} || q{};
|
||||
}
|
||||
|
||||
sub get_geometry {
|
||||
my ($self) = @_;
|
||||
return $self->{geometry} || q{};
|
||||
}
|
||||
|
||||
sub set_username {
|
||||
my ( $self, $new_username ) = @_;
|
||||
$self->{username} = $new_username;
|
||||
|
@ -92,6 +130,18 @@ sub set_port {
|
|||
return $self;
|
||||
}
|
||||
|
||||
sub set_type {
|
||||
my ( $self, $type ) = @_;
|
||||
$self->{type} = $type;
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub set_geometry {
|
||||
my ( $self, $geometry ) = @_;
|
||||
$self->{geometry} = $geometry;
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub get_master {
|
||||
my ($self) = @_;
|
||||
return $self->{master} || q{};
|
||||
|
@ -107,21 +157,16 @@ sub get_realname {
|
|||
my ($self) = @_;
|
||||
|
||||
if ( !$self->{realname} ) {
|
||||
if ( $self->{type} && $self->{type} eq 'name' ) {
|
||||
if ( $ssh_hostname_for{ $self->{hostname} } ) {
|
||||
$self->{realname} = $self->{hostname};
|
||||
}
|
||||
else {
|
||||
my $gethost_obj = gethostbyname( $self->{hostname} );
|
||||
|
||||
$self->{realname}
|
||||
= defined($gethost_obj)
|
||||
? $gethost_obj->name()
|
||||
: $self->{hostname};
|
||||
}
|
||||
if ( $self->get_type eq 'ssh_alias' ) {
|
||||
$self->{realname} = $self->{hostname};
|
||||
}
|
||||
else {
|
||||
$self->{realname} = $self->{hostname};
|
||||
my $gethost_obj = gethostbyname( $self->{hostname} );
|
||||
|
||||
$self->{realname}
|
||||
= defined($gethost_obj)
|
||||
? $gethost_obj->name()
|
||||
: $self->{hostname};
|
||||
}
|
||||
}
|
||||
return $self->{realname};
|
||||
|
@ -136,22 +181,27 @@ sub parse_host_string {
|
|||
# check for bracketed IPv6 addresses
|
||||
if ($host_string =~ m{
|
||||
\A
|
||||
(?:(.*?)@)? # username@ (optional)
|
||||
\[([\w:]*)\] # [<sequence of chars>]
|
||||
(?::(\d+))? # :port (optional)
|
||||
(?:(.*?)@)? # username@ (optional)
|
||||
\[([\w:]*)\] # [<sequence of chars>]
|
||||
(?::(\d+))? # :port (optional)
|
||||
(?:=(\d+\D\d+\D\d+\D\d))? # =geometry (optional)
|
||||
\z
|
||||
}xms
|
||||
)
|
||||
{
|
||||
$self->debug(
|
||||
5,
|
||||
$self->loc( 'bracketed IPv6: u=[_1] h=[_2] p=[_3]', $1, $2, $3 ),
|
||||
$self->loc(
|
||||
'bracketed IPv6: u=[_1] h=[_2] p=[_3] g=[_4]',
|
||||
$1, $2, $3, $4
|
||||
),
|
||||
);
|
||||
return __PACKAGE__->new(
|
||||
parse_string => $parse_string,
|
||||
username => $1,
|
||||
hostname => $2,
|
||||
port => $3,
|
||||
geometry => $4,
|
||||
type => 'ipv6',
|
||||
);
|
||||
}
|
||||
|
@ -159,58 +209,82 @@ sub parse_host_string {
|
|||
# check for standard IPv4 host.domain/IP address
|
||||
if ($host_string =~ m{
|
||||
\A
|
||||
(?:(.*?)@)? # username@ (optional)
|
||||
([\w\.-]*) # hostname[.domain[.domain] | 123.123.123.123
|
||||
(?::(\d+))? # :port (optional)
|
||||
(?:(.*?)@)? # username@ (optional)
|
||||
([\w\.-]*) # hostname[.domain[.domain] | 123.123.123.123
|
||||
(?::(\d+))? # :port (optional)
|
||||
(?:=(\d+\D\d+\D\d+\D\d+))? # =geometry (optional)
|
||||
\z
|
||||
}xms
|
||||
)
|
||||
{
|
||||
$self->debug( 5,
|
||||
$self->loc( 'std IPv4: u=[_1] h=[_2] p=[_3]', $1, $2, $3 ),
|
||||
$self->debug(
|
||||
5,
|
||||
$self->loc(
|
||||
'std IPv4: u=[_1] h=[_2] p=[_3] g=[_4]',
|
||||
$1, $2, $3, $4
|
||||
),
|
||||
);
|
||||
return __PACKAGE__->new(
|
||||
parse_string => $parse_string,
|
||||
username => $1,
|
||||
hostname => $2,
|
||||
port => $3,
|
||||
geometry => $4,
|
||||
type => 'ipv4',
|
||||
);
|
||||
}
|
||||
|
||||
# Check for unbracketed IPv6 addresses as best we can...
|
||||
my $username = q{};
|
||||
my $geometry = q{};
|
||||
my $port = q{};
|
||||
|
||||
# first, see if there is a username to grab
|
||||
my $username = q[];
|
||||
if ( $host_string =~ s/\A(?:(.*)@)// ) {
|
||||
if ( $host_string =~ s/\A(?:(.*?)@)// ) {
|
||||
|
||||
# catch where @ is in host_string but no text before it
|
||||
$username = $1 || q{};
|
||||
$username = $1;
|
||||
}
|
||||
|
||||
# check for any geometry settings
|
||||
if ( $host_string =~ s/(?:=(.*?)$)// ) {
|
||||
$geometry = $1;
|
||||
}
|
||||
|
||||
# Check for a '/nnnn' port definition
|
||||
if ( $host_string =~ s!(?:/(\d+)$)!! ) {
|
||||
$port = $1;
|
||||
}
|
||||
|
||||
# use number of colons as a possible indicator
|
||||
my $colon_count = $host_string =~ tr/://;
|
||||
|
||||
# if there are 7 colons assume its a full IPv6 address
|
||||
# if its 8 then assumed full IPv6 address with a port
|
||||
# also catch localhost address here
|
||||
if ( $colon_count == 7 || $host_string eq '::1' ) {
|
||||
if ( $colon_count == 7 || $colon_count == 8 || $host_string eq '::1' ) {
|
||||
if ( $colon_count == 8 ) {
|
||||
$host_string =~ s/(?::(\d+?))$//;
|
||||
$port = $1;
|
||||
}
|
||||
$self->debug(
|
||||
5,
|
||||
$self->loc(
|
||||
'IPv6: u=[_1] h=[_2] p=[_3]',
|
||||
$username, $host_string, ''
|
||||
'IPv6: u=[_1] h=[_2] p=[_3] g=[_4]',
|
||||
$username, $host_string, $port, $geometry,
|
||||
),
|
||||
);
|
||||
return __PACKAGE__->new(
|
||||
parse_string => $parse_string,
|
||||
username => $username,
|
||||
hostname => $host_string,
|
||||
port => q{},
|
||||
port => $port,
|
||||
geometry => $geometry,
|
||||
type => 'ipv6',
|
||||
);
|
||||
}
|
||||
if ( $colon_count > 1
|
||||
&& $colon_count < 8
|
||||
&& $host_string =~ m/:(\d+)$/xsm )
|
||||
&& $colon_count < 8 )
|
||||
{
|
||||
warn 'Ambiguous host string: "', $host_string, '"', $/;
|
||||
warn 'Assuming you meant "[', $host_string, ']"?', $/;
|
||||
|
@ -218,50 +292,20 @@ sub parse_host_string {
|
|||
$self->debug(
|
||||
5,
|
||||
$self->loc(
|
||||
'Ambiguous IPv6 u=[_1] h=[_2] p=[_3]', $username,
|
||||
$host_string, ''
|
||||
'Ambiguous IPv6 u=[_1] h=[_2] p=[_3] g=[_4]',
|
||||
$username, $host_string, $port, $geometry,
|
||||
)
|
||||
);
|
||||
|
||||
#warn "host_string=$host_string";
|
||||
#warn "username=$username";
|
||||
#warn $self->loc('some string to return');
|
||||
#warn 'debug done, returning';
|
||||
|
||||
return __PACKAGE__->new(
|
||||
parse_string => $parse_string,
|
||||
username => $username,
|
||||
hostname => $host_string,
|
||||
port => q{},
|
||||
port => $port,
|
||||
geometry => $geometry,
|
||||
type => 'ipv6',
|
||||
);
|
||||
}
|
||||
else {
|
||||
my $port = q{};
|
||||
if ( $host_string =~ s/:(\d+)$// ) {
|
||||
$port = $1;
|
||||
}
|
||||
|
||||
my $hostname = $host_string;
|
||||
|
||||
$self->debug(
|
||||
5,
|
||||
$self->loc(
|
||||
'Default parse u=[_1] h=[_2] p=[_3]',
|
||||
$username, $hostname, $port
|
||||
)
|
||||
);
|
||||
|
||||
return __PACKAGE__->new(
|
||||
parse_string => $parse_string,
|
||||
username => $username,
|
||||
hostname => $hostname,
|
||||
port => $port,
|
||||
type => 'name',
|
||||
);
|
||||
}
|
||||
|
||||
# Due to above rules, we'll never get this far anyhow
|
||||
|
||||
# if we got this far, we didnt parse the host_string properly
|
||||
croak(
|
||||
|
@ -280,9 +324,11 @@ sub check_ssh_hostname {
|
|||
$self->get_hostname );
|
||||
|
||||
if ( $ssh_hostname_for{ $self->get_hostname } ) {
|
||||
$self->debug( 5, 'Found' );
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
$self->debug( 5, 'Not found' );
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -297,26 +343,6 @@ use overload (
|
|||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
ClusterSSH::Host - Object representing a host.
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
use ClusterSSH::Host;
|
||||
|
||||
my $host = ClusterSSH::Host->new({
|
||||
hostname => 'hostname',
|
||||
});
|
||||
my $host = ClusterSSH::Host->parse_host_string('username@hostname:1234');
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Object representing a host. Include details to contact the host such as
|
||||
hostname/ipaddress, username and port.
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
=over 4
|
||||
|
@ -334,6 +360,10 @@ Create a new host object. 'hostname' is a required arg, 'username' and
|
|||
|
||||
=item $host->get_master
|
||||
|
||||
=item $host->get_geometry
|
||||
|
||||
=item $host->get_type
|
||||
|
||||
Return specific details about the host
|
||||
|
||||
=item $host->set_username
|
||||
|
@ -342,12 +372,16 @@ Return specific details about the host
|
|||
|
||||
=item $host->set_master
|
||||
|
||||
=item $host->set_geometry
|
||||
|
||||
=item $host->set_type
|
||||
|
||||
Set specific details about the host after its been created.
|
||||
|
||||
=item get_realname
|
||||
|
||||
If the server name provided is not an IP address (either IPv4 or IPv6)
|
||||
attempt to resolve it and retun the discovered names.
|
||||
attempt to resolve it and return the discovered names.
|
||||
|
||||
=item get_givenname
|
||||
|
||||
|
@ -363,6 +397,11 @@ Given a host string, returns a host object. Parses hosts such as
|
|||
Check the objects hostname to see whether or not it may be configured within
|
||||
the users F< $HOME/.ssh/config > configuration file
|
||||
|
||||
=item read_ssh_file
|
||||
|
||||
Method to ease reading in ssh configuration files. Used for grabbing
|
||||
hostnames for validation when used in clusters
|
||||
|
||||
=over 4
|
||||
|
||||
=item host
|
||||
|
@ -387,21 +426,3 @@ the IPv6 address or a port definition?) and assumes it is part of address.
|
|||
Use brackets to avoid seeing warning.
|
||||
|
||||
=back
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Duncan Ferguson, C<< <duncan_j_ferguson at yahoo.co.uk> >>
|
||||
|
||||
=head1 LICENSE AND COPYRIGHT
|
||||
|
||||
Copyright 1999-2010 Duncan Ferguson.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of either: the GNU General Public License as published
|
||||
by the Free Software Foundation; or the Artistic License.
|
||||
|
||||
See http://dev.perl.org/licenses/ for more information.
|
||||
|
||||
=cut
|
||||
|
||||
1;
|
||||
|
|
|
@ -1,22 +1,9 @@
|
|||
package App::ClusterSSH::L10N;
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Locale::Maketext 1.01;
|
||||
use base qw(Locale::Maketext);
|
||||
package App::ClusterSSH::L10N;
|
||||
|
||||
# This projects primary language is English
|
||||
|
||||
our %Lexicon = ( '_AUTO' => 1, );
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
ClusterSSH::L10N - Base translations module
|
||||
# ABSTRACT: ClusterSSH::L10N - Base translations module
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
|
@ -33,22 +20,15 @@ NOTE: the default language of this module is English.
|
|||
|
||||
=head1 METHODS
|
||||
|
||||
See Locale::Maketext - there are curently no extra methods in this module.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Duncan Ferguson, C<< <duncan_j_ferguson at yahoo.co.uk> >>
|
||||
|
||||
=head1 LICENSE AND COPYRIGHT
|
||||
|
||||
Copyright 1999-2010 Duncan Ferguson.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of either: the GNU General Public License as published
|
||||
by the Free Software Foundation; or the Artistic License.
|
||||
|
||||
See http://dev.perl.org/licenses/ for more information.
|
||||
See Locale::Maketext - there are currently no extra methods in this module.
|
||||
|
||||
=cut
|
||||
|
||||
use Locale::Maketext 1.01;
|
||||
use base qw(Locale::Maketext);
|
||||
|
||||
# This projects primary language is English
|
||||
|
||||
our %Lexicon = ( '_AUTO' => 1, );
|
||||
|
||||
1;
|
||||
|
|
|
@ -1,15 +1,6 @@
|
|||
package App::ClusterSSH::L10N::en;
|
||||
use base 'App::ClusterSSH::L10N';
|
||||
|
||||
%Lexicon = ( '_AUTO' => 1, );
|
||||
|
||||
1;
|
||||
|
||||
=pod
|
||||
|
||||
=head1 NAME
|
||||
|
||||
App::ClusterSSH::L10N::en - Base English translations module
|
||||
# ABSTRACT: App::ClusterSSH::L10N::en - Base English translations module
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
|
@ -22,24 +13,14 @@ App::ClusterSSH::L10N::en - Base English translations module
|
|||
L<Locale::Maketext> based translation module for ClusterSSH. See
|
||||
L<Locale::Maketext> for more information and usage.
|
||||
|
||||
=cut
|
||||
|
||||
use base 'App::ClusterSSH::L10N';
|
||||
|
||||
%Lexicon = ( '_AUTO' => 1, );
|
||||
|
||||
1;
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
No method are exported. See L<Locale::Maketext>.
|
||||
|
||||
=head1 AUTHOR
|
||||
|
||||
Duncan Ferguson, C<< <duncan_j_ferguson at yahoo.co.uk> >>
|
||||
|
||||
=head1 LICENSE AND COPYRIGHT
|
||||
|
||||
Copyright 1999-2010 Duncan Ferguson.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify it
|
||||
under the terms of either: the GNU General Public License as published
|
||||
by the Free Software Foundation; or the Artistic License.
|
||||
|
||||
See http://dev.perl.org/licenses/ for more information.
|
||||
|
||||
=cut
|
||||
|
||||
1;
|
||||
|
|
89
lib/App/ClusterSSH/Range.pm
Normal file
89
lib/App/ClusterSSH/Range.pm
Normal file
|
@ -0,0 +1,89 @@
|
|||
use strict;
|
||||
use warnings;
|
||||
|
||||
package App::ClusterSSH::Range;
|
||||
|
||||
# ABSTRACT: Expand ranges such as {0..1} as well as other bsd_glob specs
|
||||
|
||||
=head1 SYNOPSIS
|
||||
|
||||
use App::ClusterSSH::Range;
|
||||
my $range=App::ClusterSSH::Range->new();
|
||||
my @list = $range->expand('range{0..5}');
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Perform string expansion looking for ranges before then finishing off
|
||||
using C<File::Glob::bsd_glob>.
|
||||
|
||||
=cut
|
||||
|
||||
use File::Glob;
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
=over 4
|
||||
|
||||
=item $range = App::ClusterSSH::Range->new();
|
||||
|
||||
Create a new object to perform range processing
|
||||
|
||||
=cut
|
||||
|
||||
sub new {
|
||||
my ( $class, %args ) = @_;
|
||||
my $self = {%args};
|
||||
return bless $self, $class;
|
||||
}
|
||||
|
||||
=item @expanded = $range->expand(@strings);
|
||||
|
||||
Expand the given strings. Ranges are checked for and processed. The
|
||||
resulting string is then put through File::Glob::bsd_glob before being returned.
|
||||
|
||||
Ranges are of the form:
|
||||
|
||||
base{start..stop}
|
||||
a{0..3} => a0 a1 a2 a3
|
||||
b{4..6,9,12..14} => b4 b5 b6 b9 b12 b13 b14
|
||||
|
||||
=back
|
||||
|
||||
=cut
|
||||
|
||||
sub expand {
|
||||
my ( $self, @items ) = @_;
|
||||
|
||||
my $range_regexp = qr/[\w-]*:?\{[\w\.,]+\}/;
|
||||
my @newlist;
|
||||
foreach my $item (@items) {
|
||||
if ( $item !~ m/$range_regexp/ ) {
|
||||
push( @newlist, $item );
|
||||
next;
|
||||
}
|
||||
|
||||
my ( $base, $spec ) = $item =~ m/^(.*?\{(.*?)\}.*?)$/;
|
||||
|
||||
for my $section ( split( /,/, $spec ) ) {
|
||||
my ( $start, $end );
|
||||
|
||||
if ( $section =~ m/\.\./ ) {
|
||||
( $start, $end ) = split( /\.\./, $section, 2 );
|
||||
}
|
||||
|
||||
$start = $section if ( !defined($start) );
|
||||
$end = $start if ( !defined($end) );
|
||||
|
||||
foreach my $number ( $start .. $end ) {
|
||||
( my $changed = $base ) =~ s/\{$spec\}/$number/;
|
||||
push( @newlist, $changed );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
my @text = map { File::Glob::bsd_glob($_) } @newlist;
|
||||
|
||||
return wantarray ? @text : "@text";
|
||||
}
|
||||
|
||||
1;
|
68
lib/App/ClusterSSH/Window.pm
Normal file
68
lib/App/ClusterSSH/Window.pm
Normal file
|
@ -0,0 +1,68 @@
|
|||
use strict;
|
||||
use warnings;
|
||||
|
||||
package App::ClusterSSH::Window;
|
||||
|
||||
# ABSTRACT: App::ClusterSSH::Window - Base obejct for different types of window module
|
||||
|
||||
=head1 DESCRIPTION
|
||||
|
||||
Base object to allow for configuring and using different types of windows libraries
|
||||
|
||||
=cut
|
||||
|
||||
=head1 METHODS
|
||||
|
||||
=over 4
|
||||
|
||||
=cut
|
||||
|
||||
use Carp;
|
||||
|
||||
use base qw/ App::ClusterSSH::Base /;
|
||||
|
||||
# Module to contain window generic code and pull in specific code from
|
||||
# an appropriate module
|
||||
|
||||
sub import {
|
||||
my ($class) = @_;
|
||||
|
||||
# If we are building or in test here, just exit
|
||||
# as the build servers will not have Tk installed
|
||||
if ( $ENV{AUTHOR_TESTING} || $ENV{RELEASE_TESTING} ) {
|
||||
print STDERR
|
||||
"skipping initialisation; AUTHOR_TESTING or RELEASE_TESTING are set\n";
|
||||
return;
|
||||
}
|
||||
|
||||
# Find what windows module we should be using and just overlay it into
|
||||
# this object
|
||||
my $package_name = __PACKAGE__ . '::Tk';
|
||||
( my $package_path = $package_name ) =~ s{::}{/}g;
|
||||
require "$package_path.pm";
|
||||
$package_name->import();
|
||||
|
||||
{
|
||||
no strict 'refs';
|
||||
push @{ __PACKAGE__ . '::ISA' }, $package_name;
|
||||
}
|
||||
}
|
||||
|
||||
my %servers;
|
||||
|
||||
=item $obj = App::ClusterSSH::Window->new({});
|
||||
|
||||
Creates object
|
||||
|
||||
=back
|
||||
|
||||
=cut
|
||||
|
||||
sub new {
|
||||
my ( $class, %args ) = @_;
|
||||
my $self = $class->SUPER::new(%args);
|
||||
|
||||
return $self;
|
||||
}
|
||||
|
||||
1;
|
2037
lib/App/ClusterSSH/Window/Tk.pm
Normal file
2037
lib/App/ClusterSSH/Window/Tk.pm
Normal file
File diff suppressed because it is too large
Load diff
182
t/02base.t
182
t/02base.t
|
@ -19,12 +19,12 @@ isa_ok( $base, 'App::ClusterSSH::Base' );
|
|||
|
||||
diag('testing output') if ( $ENV{TEST_VERBOSE} );
|
||||
trap {
|
||||
$base->output('testing');
|
||||
$base->stdout_output('testing');
|
||||
};
|
||||
is( $trap->leaveby, 'return', 'returned ok' );
|
||||
is( $trap->die, undef, 'returned ok' );
|
||||
is( $trap->stderr, '', 'Expecting no STDERR' );
|
||||
is( $trap->stdout =~ tr/\n//, 1, 'got correct number of print lines' );
|
||||
is( $trap->leaveby, 'return', 'returned ok' );
|
||||
is( $trap->die, undef, 'returned ok' );
|
||||
is( $trap->stderr, '', 'Expecting no STDERR' );
|
||||
is( $trap->stdout =~ tr/\n//, 1, 'got correct number of print lines' );
|
||||
like( $trap->stdout, qr/\Atesting\n\Z/xsm,
|
||||
'checking for expected print output' );
|
||||
|
||||
|
@ -68,10 +68,10 @@ trap {
|
|||
$base = App::ClusterSSH::Base->new( debug => 6, );
|
||||
};
|
||||
isa_ok( $base, 'App::ClusterSSH::Base' );
|
||||
is( $trap->leaveby, 'return', 'returned ok' );
|
||||
is( $trap->die, undef, 'returned ok' );
|
||||
is( $trap->stderr, '', 'Expecting no STDERR' );
|
||||
is( $trap->stdout =~ tr/\n//, 1, 'got new() debug output lines' );
|
||||
is( $trap->leaveby, 'return', 'returned ok' );
|
||||
is( $trap->die, undef, 'returned ok' );
|
||||
is( $trap->stderr, '', 'Expecting no STDERR' );
|
||||
is( $trap->stdout =~ tr/\n//, 1, 'got new() debug output lines' );
|
||||
like(
|
||||
$trap->stdout,
|
||||
qr/^Setting\slanguage\sto\s"en"/xsm,
|
||||
|
@ -83,10 +83,10 @@ trap {
|
|||
$base = App::ClusterSSH::Base->new( debug => 6, lang => 'en' );
|
||||
};
|
||||
isa_ok( $base, 'App::ClusterSSH::Base' );
|
||||
is( $trap->leaveby, 'return', 'returned ok' );
|
||||
is( $trap->die, undef, 'returned ok' );
|
||||
is( $trap->stderr, '', 'Expecting no STDERR' );
|
||||
is( $trap->stdout =~ tr/\n//, 1, 'got new() debug output lines' );
|
||||
is( $trap->leaveby, 'return', 'returned ok' );
|
||||
is( $trap->die, undef, 'returned ok' );
|
||||
is( $trap->stderr, '', 'Expecting no STDERR' );
|
||||
is( $trap->stdout =~ tr/\n//, 1, 'got new() debug output lines' );
|
||||
like(
|
||||
$trap->stdout,
|
||||
qr/^Setting\slanguage\sto\s"en"/xsm,
|
||||
|
@ -98,10 +98,10 @@ trap {
|
|||
$base = App::ClusterSSH::Base->new( debug => 6, lang => 'rubbish' );
|
||||
};
|
||||
isa_ok( $base, 'App::ClusterSSH::Base' );
|
||||
is( $trap->leaveby, 'return', 'returned ok' );
|
||||
is( $trap->die, undef, 'returned ok' );
|
||||
is( $trap->stderr, '', 'Expecting no STDERR' );
|
||||
is( $trap->stdout =~ tr/\n//, 1, 'got new() debug output lines' );
|
||||
is( $trap->leaveby, 'return', 'returned ok' );
|
||||
is( $trap->die, undef, 'returned ok' );
|
||||
is( $trap->stderr, '', 'Expecting no STDERR' );
|
||||
is( $trap->stdout =~ tr/\n//, 1, 'got new() debug output lines' );
|
||||
like(
|
||||
$trap->stdout,
|
||||
qr/^Setting\slanguage\sto\s"rubbish"/xsm,
|
||||
|
@ -109,23 +109,29 @@ like(
|
|||
);
|
||||
|
||||
$base = undef;
|
||||
my $get_config;
|
||||
trap {
|
||||
$base = App::ClusterSSH::Base->new( debug => 7, );
|
||||
};
|
||||
isa_ok( $base, 'App::ClusterSSH::Base' );
|
||||
is( $trap->leaveby, 'return', 'returned ok' );
|
||||
is( $trap->die, undef, 'returned ok' );
|
||||
is( $trap->stderr, '', 'Expecting no STDERR' );
|
||||
is( $trap->stdout =~ tr/\n//, 3, 'got new() debug output lines' );
|
||||
is( $trap->leaveby, 'return', 'returned ok' );
|
||||
is( $trap->die, undef, 'returned ok' );
|
||||
is( $trap->stderr, '', 'Expecting no STDERR' );
|
||||
is( $trap->stdout =~ tr/\n//, 3, 'got new() debug output lines' );
|
||||
like(
|
||||
$trap->stdout,
|
||||
qr/^Setting\slanguage\sto\s"en".Arguments\sto\sApp::ClusterSSH::Base->new.*debug\s=>\s7,$/xsm,
|
||||
'got expected new() output'
|
||||
);
|
||||
|
||||
trap {
|
||||
$get_config = $base->config();
|
||||
};
|
||||
$trap->quiet("No issus with config call");
|
||||
is( $get_config, undef, "config set undef as expected" );
|
||||
|
||||
# config tests
|
||||
$base = undef;
|
||||
my $get_config;
|
||||
my $object;
|
||||
trap {
|
||||
$base = App::ClusterSSH::Base->new( debug => 3, );
|
||||
|
@ -136,6 +142,17 @@ is( $trap->die, undef, 'returned ok' );
|
|||
is( $trap->stderr, '', 'Expecting no STDERR' );
|
||||
is( $trap->stdout, '', 'Expecting no STDOUT' );
|
||||
|
||||
$base = undef;
|
||||
trap {
|
||||
$base = App::ClusterSSH::Base->new( debug => 3, parent => 'guardian' );
|
||||
};
|
||||
isa_ok( $base, 'App::ClusterSSH::Base' );
|
||||
is( $trap->leaveby, 'return', 'returned ok' );
|
||||
is( $trap->die, undef, 'returned ok' );
|
||||
is( $trap->stderr, '', 'Expecting no STDERR' );
|
||||
is( $trap->stdout, '', 'Expecting no STDOUT' );
|
||||
is( $base->parent, 'guardian', 'Expecting no STDOUT' );
|
||||
|
||||
trap {
|
||||
$get_config = $base->config();
|
||||
};
|
||||
|
@ -208,4 +225,125 @@ like(
|
|||
is( $trap->stderr, '', 'Expecting no STDERR' );
|
||||
is( $trap->stdout, '', 'Got expected STDOUT' );
|
||||
|
||||
# basic checks - validity of config is tested elsewhere
|
||||
my %config;
|
||||
trap {
|
||||
%config = $object->load_file;
|
||||
};
|
||||
is( $trap->leaveby, 'die', 'died ok' );
|
||||
isa_ok( $trap->die, 'App::ClusterSSH::Exception',
|
||||
'Caught exception object OK' );
|
||||
is( $trap->die,
|
||||
q{"filename" arg not passed},
|
||||
'missing filename arg die message'
|
||||
);
|
||||
is( $trap->stderr, '', 'Expecting no STDERR' );
|
||||
is( $trap->stdout, '', 'Got expected STDOUT' );
|
||||
|
||||
trap {
|
||||
%config = $object->load_file( filename => $Bin . '/15config.t.file1' );
|
||||
};
|
||||
is( $trap->leaveby, 'die', 'died ok' );
|
||||
isa_ok( $trap->die, 'App::ClusterSSH::Exception',
|
||||
'Caught exception object OK' );
|
||||
is( $trap->die, q{"type" arg not passed}, 'missing type arg die message' );
|
||||
is( $trap->stderr, '', 'Expecting no STDERR' );
|
||||
|
||||
my $get_options;
|
||||
|
||||
$base = undef;
|
||||
trap {
|
||||
$base = App::ClusterSSH::Base->new( debug => 3 );
|
||||
};
|
||||
isa_ok( $base, 'App::ClusterSSH::Base' );
|
||||
is( $trap->leaveby, 'return', 'returned ok' );
|
||||
is( $trap->die, undef, 'returned ok' );
|
||||
is( $trap->stderr, '', 'Expecting no STDERR' );
|
||||
is( $trap->stdout, '', 'Expecting no STDOUT' );
|
||||
is( $base->parent, undef, 'Expecting no parent set' );
|
||||
|
||||
trap {
|
||||
$get_options = $base->options();
|
||||
};
|
||||
$trap->quiet("No extra output");
|
||||
is( $get_options, undef, "options call correctly unset" );
|
||||
|
||||
$base = undef;
|
||||
trap {
|
||||
$base = App::ClusterSSH::Base->new( debug => 3, parent => 'guardian' );
|
||||
};
|
||||
isa_ok( $base, 'App::ClusterSSH::Base' );
|
||||
is( $trap->leaveby, 'return', 'returned ok' );
|
||||
is( $trap->die, undef, 'returned ok' );
|
||||
is( $trap->stderr, '', 'Expecting no STDERR' );
|
||||
is( $trap->stdout, '', 'Expecting no STDOUT' );
|
||||
is( $base->parent, 'guardian', 'Expecting no STDOUT' );
|
||||
|
||||
trap {
|
||||
$get_options = $base->options();
|
||||
};
|
||||
$trap->quiet("No extra output");
|
||||
is( $get_options, undef, "options call correctly unset" );
|
||||
|
||||
$base = undef;
|
||||
trap {
|
||||
$base = App::ClusterSSH::Base->new(
|
||||
debug => 3,
|
||||
parent => { config => 'set', options => 'set' }
|
||||
);
|
||||
};
|
||||
isa_ok( $base, 'App::ClusterSSH::Base' );
|
||||
is( $trap->leaveby, 'return', 'returned ok' );
|
||||
is( $trap->die, undef, 'returned ok' );
|
||||
is( $trap->stderr, '', 'Expecting no STDERR' );
|
||||
is( $trap->stdout, '', 'Expecting no STDOUT' );
|
||||
is( ref( $base->parent ), 'HASH', 'Expecting no STDOUT' );
|
||||
is( $base->parent->{config}, 'set', 'Expecting no STDOUT' );
|
||||
|
||||
trap {
|
||||
$get_options = $base->options();
|
||||
};
|
||||
is( ref($get_options), '', "options call correctly set" );
|
||||
is( $get_options, 'set', "options call hash value correctly set" );
|
||||
$trap->quiet("No extra output");
|
||||
|
||||
my $sort;
|
||||
trap {
|
||||
$sort = $base->sort;
|
||||
};
|
||||
$trap->quiet("No errors getting 'sort'");
|
||||
|
||||
# NOTE: trap doesnt like passing code refs, so recreate here
|
||||
$sort = $base->sort;
|
||||
is( ref($sort), 'CODE', "got results from sort" );
|
||||
my @sorted = $sort->( 4, 8, 1, 5, 3 );
|
||||
my @expected = ( 1, 3, 4, 5, 8 );
|
||||
is_deeply( \@sorted, \@expected, "simple sort results okay" );
|
||||
|
||||
$base = undef;
|
||||
trap {
|
||||
$base = App::ClusterSSH::Base->new(
|
||||
debug => 3,
|
||||
parent => { config => { use_natural_sort => 1 }, options => 'set' }
|
||||
);
|
||||
};
|
||||
isa_ok( $base, 'App::ClusterSSH::Base' );
|
||||
is( $trap->leaveby, 'return', 'returned ok' );
|
||||
is( $trap->die, undef, 'returned ok' );
|
||||
is( $trap->stderr, '', 'Expecting no STDERR' );
|
||||
is( $trap->stdout, '', 'Expecting no STDOUT' );
|
||||
|
||||
trap {
|
||||
$sort = $base->sort;
|
||||
};
|
||||
|
||||
# May get an error here if Sort::Naturally is not installed
|
||||
# $trap->quiet("No errors getting 'sort'");
|
||||
is( $trap->leaveby, 'return', 'returned ok' );
|
||||
is( $trap->die, undef, 'returned ok' );
|
||||
is( ref($sort), 'CODE', "got results from sort" );
|
||||
@sorted = $sort->( 4, 8, 1, 5, 3 );
|
||||
@expected = ( 1, 3, 4, 5, 8 );
|
||||
is_deeply( \@sorted, \@expected, "simple sort results okay" );
|
||||
|
||||
done_testing();
|
||||
|
|
439
t/05getopts.t
Normal file
439
t/05getopts.t
Normal file
|
@ -0,0 +1,439 @@
|
|||
use strict;
|
||||
use warnings;
|
||||
|
||||
# Force use of English in tests for the moment, for those users that
|
||||
# have a different locale set, since errors are hardcoded below
|
||||
use POSIX qw(setlocale locale_h);
|
||||
setlocale( LC_ALL, "C" );
|
||||
|
||||
package Test::ClusterSSH::Mock;
|
||||
|
||||
# generate purpose object used to simplfy testing
|
||||
|
||||
sub new {
|
||||
my ( $class, %args ) = @_;
|
||||
my $config = {
|
||||
comms => 'testing',
|
||||
key_addhost => 'x',
|
||||
key_clientname => 'x',
|
||||
key_localname => 'x',
|
||||
key_quit => 'x',
|
||||
key_retilehosts => 'x',
|
||||
key_username => 'x',
|
||||
%args
|
||||
};
|
||||
return bless $config, $class;
|
||||
}
|
||||
|
||||
sub parent {
|
||||
my ($self) = @_;
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub VERSION {
|
||||
my ($self) = @_;
|
||||
return 'TESTING';
|
||||
}
|
||||
|
||||
sub config {
|
||||
my ($self) = @_;
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub load_configs {
|
||||
my ($self) = @_;
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub config_file {
|
||||
my ($self) = @_;
|
||||
return {};
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
package main;
|
||||
|
||||
use FindBin qw($Bin);
|
||||
use lib "$Bin/../lib";
|
||||
|
||||
use Test::More;
|
||||
use Test::Trap;
|
||||
|
||||
BEGIN { use_ok('App::ClusterSSH::Getopt') }
|
||||
|
||||
my $getopts;
|
||||
|
||||
my $mock_object = Test::ClusterSSH::Mock->new();
|
||||
|
||||
$getopts = App::ClusterSSH::Getopt->new( parent => $mock_object );
|
||||
isa_ok( $getopts, 'App::ClusterSSH::Getopt' );
|
||||
trap {
|
||||
$getopts->getopts;
|
||||
};
|
||||
is( $trap->leaveby, 'return', 'getops on new object okay' );
|
||||
is( $trap->stdout, '', 'Expecting no STDOUT' );
|
||||
is( $trap->stderr, '', 'Expecting no STDERR' );
|
||||
is( $trap->die, undef, 'Expecting no die message' );
|
||||
|
||||
$getopts = App::ClusterSSH::Getopt->new( parent => $mock_object );
|
||||
isa_ok( $getopts, 'App::ClusterSSH::Getopt' );
|
||||
|
||||
trap {
|
||||
$getopts->add_option();
|
||||
};
|
||||
is( $trap->leaveby, 'die', 'adding an empty option failed' );
|
||||
is( $trap->die,
|
||||
q{No "spec" passed to add_option},
|
||||
'empty add_option message'
|
||||
);
|
||||
is( $trap->stdout, '', 'Expecting no STDOUT' );
|
||||
is( $trap->stderr, '', 'Expecting no STDERR' );
|
||||
|
||||
trap {
|
||||
$getopts->add_option( spec => 'option' );
|
||||
};
|
||||
is( $trap->leaveby, 'return', 'adding an empty option failed' );
|
||||
is( $trap->die, undef, 'no error when spec provided' );
|
||||
is( $trap->stdout, '', 'Expecting no STDOUT' );
|
||||
is( $trap->stderr, '', 'Expecting no STDERR' );
|
||||
trap {
|
||||
$getopts->getopts;
|
||||
};
|
||||
is( $trap->leaveby, 'return', 'getops on object with spec okay' );
|
||||
is( $trap->stdout, '', 'Expecting no STDOUT' );
|
||||
is( $trap->stderr, '', 'Expecting no STDERR' );
|
||||
is( $trap->die, undef, 'Expecting no die message' );
|
||||
trap {
|
||||
$getopts->option;
|
||||
};
|
||||
is( $trap->leaveby, 'return', 'calling option' );
|
||||
is( $trap->stdout, '', 'Expecting no STDOUT' );
|
||||
is( $trap->stderr, '', 'Expecting no STDERR' );
|
||||
is( $trap->die, undef, 'Expecting no die message' );
|
||||
is( $getopts->option, undef, 'Expecting no die message' );
|
||||
|
||||
local @ARGV = '--option1';
|
||||
$getopts = App::ClusterSSH::Getopt->new( parent => $mock_object );
|
||||
trap {
|
||||
$getopts->add_option( spec => 'option1' );
|
||||
};
|
||||
is( $trap->leaveby, 'return', 'adding an empty option failed' );
|
||||
is( $trap->die, undef, 'no error when spec provided' );
|
||||
is( $trap->stdout, '', 'Expecting no STDOUT' );
|
||||
is( $trap->stderr, '', 'Expecting no STDERR' );
|
||||
trap {
|
||||
$getopts->getopts;
|
||||
};
|
||||
is( $trap->leaveby, 'return', 'getops on object with spec okay' );
|
||||
is( $trap->stdout, '', 'Expecting no STDOUT' );
|
||||
is( $trap->stderr, '', 'Expecting no STDERR' );
|
||||
is( $trap->die, undef, 'Expecting no die message' );
|
||||
trap {
|
||||
$getopts->option1;
|
||||
};
|
||||
is( $trap->leaveby, 'return', 'calling option' );
|
||||
is( $trap->stdout, '', 'Expecting no STDOUT' );
|
||||
is( $trap->stderr, '', 'Expecting no STDERR' );
|
||||
is( $trap->die, undef, 'Expecting no die message' );
|
||||
is( $getopts->option1, 1, 'Expecting no die message' );
|
||||
|
||||
local @ARGV = ''; # @ARGV is never undef, but an empty string
|
||||
$getopts = App::ClusterSSH::Getopt->new( parent => $mock_object );
|
||||
trap {
|
||||
$getopts->add_option( spec => 'option1', default => 5 );
|
||||
};
|
||||
is( $trap->leaveby, 'return', 'adding an empty option with a default value' );
|
||||
is( $trap->die, undef, 'no error when spec provided' );
|
||||
is( $trap->stdout, '', 'Expecting no STDOUT' );
|
||||
is( $trap->stderr, '', 'Expecting no STDERR' );
|
||||
trap {
|
||||
$getopts->getopts;
|
||||
};
|
||||
is( $trap->leaveby, 'return', 'getops on object with spec okay' );
|
||||
is( $trap->stdout, '', 'Expecting no STDOUT' );
|
||||
is( $trap->stderr, '', 'Expecting no STDERR' );
|
||||
is( $trap->die, undef, 'Expecting no die message' );
|
||||
trap {
|
||||
$getopts->option1;
|
||||
};
|
||||
is( $trap->leaveby, 'return', 'calling option' );
|
||||
is( $trap->stdout, '', 'Expecting no STDOUT' );
|
||||
is( $trap->stderr, '', 'Expecting no STDERR' );
|
||||
is( $trap->die, undef, 'Expecting no die message' );
|
||||
is( $getopts->option1, 5, 'correct default value' );
|
||||
|
||||
local @ARGV = ( '--option1', '8' );
|
||||
$getopts = App::ClusterSSH::Getopt->new( parent => $mock_object );
|
||||
trap {
|
||||
$getopts->add_option( spec => 'option1=i', default => 5, );
|
||||
};
|
||||
is( $trap->leaveby, 'return', 'adding an empty option failed' );
|
||||
is( $trap->die, undef, 'no error when spec provided' );
|
||||
is( $trap->stdout, '', 'Expecting no STDOUT' );
|
||||
is( $trap->stderr, '', 'Expecting no STDERR' );
|
||||
trap {
|
||||
$getopts->getopts;
|
||||
};
|
||||
is( $trap->leaveby, 'return', 'getops on object with spec okay' );
|
||||
is( $trap->stdout, '', 'Expecting no STDOUT' );
|
||||
is( $trap->stderr, '', 'Expecting no STDERR' );
|
||||
is( $trap->die, undef, 'Expecting no die message' );
|
||||
trap {
|
||||
$getopts->option1;
|
||||
};
|
||||
is( $trap->leaveby, 'return', 'calling option' );
|
||||
is( $trap->stdout, '', 'Expecting no STDOUT' );
|
||||
is( $trap->stderr, '', 'Expecting no STDERR' );
|
||||
is( $trap->die, undef, 'Expecting no die message' );
|
||||
is( $getopts->option1, 8, 'default value overridden' );
|
||||
|
||||
@ARGV = ( '--option1', '--option2', 'string', '--option3', '10' );
|
||||
$getopts = App::ClusterSSH::Getopt->new( parent => $mock_object );
|
||||
trap {
|
||||
$getopts->add_option( spec => 'hidden', hidden => 1, no_acessor => 1, );
|
||||
};
|
||||
is( $trap->leaveby, 'return', 'adding an empty option failed' );
|
||||
is( $trap->die, undef, 'no error when spec provided' );
|
||||
is( $trap->stdout, '', 'Expecting no STDOUT' );
|
||||
is( $trap->stderr, '', 'Expecting no STDERR' );
|
||||
trap {
|
||||
$getopts->add_option( spec => 'option1', help => 'help for 1' );
|
||||
};
|
||||
is( $trap->leaveby, 'return', 'adding an empty option failed' );
|
||||
is( $trap->die, undef, 'no error when spec provided' );
|
||||
is( $trap->stdout, '', 'Expecting no STDOUT' );
|
||||
is( $trap->stderr, '', 'Expecting no STDERR' );
|
||||
trap {
|
||||
$getopts->add_option( spec => 'option2|o=s', help => 'help for 2' );
|
||||
};
|
||||
is( $trap->leaveby, 'return', 'adding option2 failed' );
|
||||
is( $trap->die, undef, 'no error when spec provided' );
|
||||
is( $trap->stdout, '', 'Expecting no STDOUT' );
|
||||
is( $trap->stderr, '', 'Expecting no STDERR' );
|
||||
trap {
|
||||
$getopts->add_option(
|
||||
spec => 'option3|alt_opt|O=i',
|
||||
help => 'help for 3',
|
||||
default => 5
|
||||
);
|
||||
};
|
||||
is( $trap->leaveby, 'return', 'adding option3 failed' );
|
||||
is( $trap->die, undef, 'no error when spec provided' );
|
||||
is( $trap->stdout, '', 'Expecting no STDOUT' );
|
||||
is( $trap->stderr, '', 'Expecting no STDERR' );
|
||||
trap {
|
||||
$getopts->getopts;
|
||||
};
|
||||
is( $trap->leaveby, 'return', 'getops on object with spec okay' );
|
||||
is( $trap->stdout, '', 'Expecting no STDOUT' );
|
||||
is( $trap->stderr, '', 'Expecting no STDERR' );
|
||||
is( $trap->die, undef, 'Expecting no die message' );
|
||||
trap {
|
||||
$getopts->option1;
|
||||
};
|
||||
is( $trap->leaveby, 'return', 'calling option1' );
|
||||
is( $trap->stdout, '', 'Expecting no STDOUT' );
|
||||
is( $trap->stderr, '', 'Expecting no STDERR' );
|
||||
is( $trap->die, undef, 'Expecting no die message' );
|
||||
is( $getopts->option1, 1, 'option1 is as expected' );
|
||||
trap {
|
||||
$getopts->option1;
|
||||
};
|
||||
is( $trap->leaveby, 'return', 'calling option2' );
|
||||
is( $trap->stdout, '', 'Expecting no STDOUT' );
|
||||
is( $trap->stderr, '', 'Expecting no STDERR' );
|
||||
is( $trap->die, undef, 'Expecting no die message' );
|
||||
is( $getopts->option2, 'string', 'option2 is as expected' );
|
||||
trap {
|
||||
$getopts->option3;
|
||||
};
|
||||
is( $trap->leaveby, 'return', 'calling option3' );
|
||||
is( $trap->stdout, '', 'Expecting no STDOUT' );
|
||||
is( $trap->stderr, '', 'Expecting no STDERR' );
|
||||
is( $trap->die, undef, 'Expecting no die message' );
|
||||
is( $getopts->option3, 10, 'option3 is as expected' );
|
||||
|
||||
$getopts = App::ClusterSSH::Getopt->new( parent => $mock_object );
|
||||
trap {
|
||||
$getopts->add_common_ssh_options;
|
||||
};
|
||||
is( $trap->leaveby, 'return', 'calling option2' );
|
||||
is( $trap->stdout, '', 'Expecting no STDOUT' );
|
||||
is( $trap->stderr, '', 'Expecting no STDERR' );
|
||||
is( $trap->die, undef, 'Expecting no die message' );
|
||||
trap {
|
||||
$getopts->getopts;
|
||||
};
|
||||
is( $trap->leaveby, 'return', 'getops on object with spec okay' );
|
||||
is( $trap->stdout, '', 'Expecting no STDOUT' );
|
||||
is( $trap->stderr, '', 'Expecting no STDERR' );
|
||||
is( $trap->die, undef, 'Expecting no die message' );
|
||||
|
||||
$getopts = App::ClusterSSH::Getopt->new( parent => $mock_object );
|
||||
trap {
|
||||
$getopts->add_common_session_options;
|
||||
};
|
||||
is( $trap->leaveby, 'return', 'calling option2' );
|
||||
is( $trap->stdout, '', 'Expecting no STDOUT' );
|
||||
is( $trap->stderr, '', 'Expecting no STDERR' );
|
||||
is( $trap->die, undef, 'Expecting no die message' );
|
||||
trap {
|
||||
$getopts->getopts;
|
||||
};
|
||||
is( $trap->leaveby, 'return', 'getops on object with spec okay' );
|
||||
is( $trap->stdout, '', 'Expecting no STDOUT' );
|
||||
is( $trap->stderr, '', 'Expecting no STDERR' );
|
||||
is( $trap->die, undef, 'Expecting no die message' );
|
||||
|
||||
my $pod;
|
||||
@ARGV = ('--generate-pod');
|
||||
$getopts = App::ClusterSSH::Getopt->new( parent => $mock_object );
|
||||
$getopts->add_option(
|
||||
spec => 'long_opt|l=s',
|
||||
help => 'long opt help',
|
||||
default => 'default string'
|
||||
);
|
||||
$getopts->add_option( spec => 'another_long_opt|n=i', );
|
||||
$getopts->add_option( spec => 'a=s', help => 'short option only', );
|
||||
$getopts->add_option( spec => 'long', help => 'long option only', );
|
||||
trap {
|
||||
$getopts->getopts;
|
||||
};
|
||||
is( $trap->leaveby, 'exit', 'adding an empty option failed' );
|
||||
is( $trap->die, undef, 'no error when spec provided' );
|
||||
ok( defined( $trap->stdout ), 'Expecting no STDOUT' );
|
||||
$pod = $trap->stdout;
|
||||
|
||||
# run pod through a checker at some point as it should be 'clean'
|
||||
is( $trap->stderr, '', 'Expecting no STDERR' );
|
||||
is( $trap->die, undef, 'Expecting no die message' );
|
||||
|
||||
@ARGV = ('--help');
|
||||
$getopts = App::ClusterSSH::Getopt->new( parent => $mock_object );
|
||||
trap {
|
||||
$getopts->getopts;
|
||||
};
|
||||
is( $trap->leaveby, 'exit', 'adding an empty option failed' );
|
||||
is( $trap->die, undef, 'no error when spec provided' );
|
||||
ok( defined( $trap->stdout ), 'Expecting no STDOUT' );
|
||||
is( $trap->stderr, '', 'Expecting no STDERR' );
|
||||
is( $trap->die, undef, 'Expecting no die message' );
|
||||
|
||||
@ARGV = ('-?');
|
||||
$getopts = App::ClusterSSH::Getopt->new( parent => $mock_object );
|
||||
trap {
|
||||
$getopts->getopts;
|
||||
};
|
||||
is( $trap->leaveby, 'exit', 'adding an empty option failed' );
|
||||
is( $trap->die, undef, 'no error when spec provided' );
|
||||
ok( defined( $trap->stdout ), 'Expecting no STDOUT' );
|
||||
is( $trap->stderr, '', 'Expecting no STDERR' );
|
||||
is( $trap->die, undef, 'Expecting no die message' );
|
||||
|
||||
@ARGV = ('-v');
|
||||
$getopts = App::ClusterSSH::Getopt->new( parent => $mock_object );
|
||||
trap {
|
||||
$getopts->getopts;
|
||||
};
|
||||
is( $trap->leaveby, 'exit', 'version option exist okay' );
|
||||
is( $trap->die, undef, 'no error when spec provided' );
|
||||
like( $trap->stdout, qr/^Version: /, 'Version string correct' );
|
||||
is( $trap->stderr, '', 'Expecting no STDERR' );
|
||||
is( $trap->die, undef, 'Expecting no die message' );
|
||||
|
||||
@ARGV = ('-@');
|
||||
$getopts = App::ClusterSSH::Getopt->new( parent => $mock_object );
|
||||
trap {
|
||||
$getopts->getopts;
|
||||
};
|
||||
is( $trap->leaveby, 'exit', 'adding an empty option failed' );
|
||||
is( $trap->die, undef, 'no error when spec provided' );
|
||||
ok( defined( $trap->stdout ), 'Expecting no STDOUT' );
|
||||
like( $trap->stderr, qr{Unknown option: @}, 'Expecting no STDERR' );
|
||||
is( $trap->die, undef, 'Expecting no die message' );
|
||||
|
||||
# test some common options
|
||||
@ARGV = (
|
||||
'--unique-servers', '--title', 'title', '-p',
|
||||
'22', '--autoquit', '--tile', '--autoclose',
|
||||
'10',
|
||||
);
|
||||
$mock_object->{auto_close} = 0;
|
||||
$mock_object->{auto_quit} = 0;
|
||||
$mock_object->{window_tiling} = 0;
|
||||
$mock_object->{show_history} = 0;
|
||||
$mock_object->{use_all_a_records} = 1;
|
||||
$getopts = App::ClusterSSH::Getopt->new( parent => $mock_object, );
|
||||
trap {
|
||||
$getopts->getopts;
|
||||
};
|
||||
is( $trap->leaveby, 'return', 'adding an empty option failed' );
|
||||
is( $trap->die, undef, 'no error when spec provided' );
|
||||
is( $trap->stdout, '', 'Expecting no STDOUT' );
|
||||
is( $trap->stderr, '', 'Expecting no STDERR' );
|
||||
is( $trap->die, undef, 'Expecting no die message' );
|
||||
is( $mock_object->{auto_close}, 10, 'auto_close set right' );
|
||||
is( $mock_object->{auto_quit}, 1, 'auto_quit set right' );
|
||||
is( $mock_object->{window_tiling}, 1, 'window_tiling set right' );
|
||||
is( $mock_object->{show_history}, 0, 'show_history set right' );
|
||||
is( $mock_object->{use_all_a_records}, 1, 'use_all_a_records set right' );
|
||||
|
||||
@ARGV = (
|
||||
'--unique-servers', '--title', 'title', '-p', '22', '--autoquit',
|
||||
'--tile', '--show-history', '-A',
|
||||
);
|
||||
$getopts = App::ClusterSSH::Getopt->new( parent => $mock_object, );
|
||||
trap {
|
||||
$getopts->getopts;
|
||||
};
|
||||
is( $trap->leaveby, 'return', 'adding an empty option failed' );
|
||||
is( $trap->die, undef, 'no error when spec provided' );
|
||||
is( $trap->stdout, '', 'Expecting no STDOUT' );
|
||||
is( $trap->stderr, '', 'Expecting no STDERR' );
|
||||
is( $trap->die, undef, 'Expecting no die message' );
|
||||
is( $mock_object->{auto_close}, 10, 'auto_close set right' );
|
||||
is( $mock_object->{auto_quit}, 0, 'auto_quit set right' );
|
||||
is( $mock_object->{window_tiling}, 0, 'window_tiling set right' );
|
||||
is( $mock_object->{show_history}, 1, 'show_history set right' );
|
||||
is( $mock_object->{use_all_a_records}, 0, 'use_all_a_records set right' );
|
||||
|
||||
TODO: {
|
||||
local $TODO = "explitely test for duplicate options";
|
||||
$getopts = App::ClusterSSH::Getopt->new(
|
||||
parent => Test::ClusterSSH::Mock->new() );
|
||||
trap {
|
||||
$getopts->add_option( spec => 'option1' );
|
||||
};
|
||||
is( $trap->leaveby, 'return', 'adding an empty option failed' );
|
||||
is( $trap->die, undef, 'no error when spec provided' );
|
||||
is( $trap->stdout, '', 'Expecting no STDOUT' );
|
||||
is( $trap->stderr, '', 'Expecting no STDERR' );
|
||||
trap {
|
||||
$getopts->add_option( spec => 'option1' );
|
||||
};
|
||||
is( $trap->leaveby, 'die', 'adding an empty option failed' );
|
||||
is( $trap->die, "bling bling", 'no error when spec provided' );
|
||||
is( $trap->stdout, 'bling bling', 'Expecting no STDOUT' );
|
||||
is( $trap->stderr, 'bling bling', 'Expecting no STDERR' );
|
||||
trap {
|
||||
$getopts->getopts;
|
||||
};
|
||||
is( $trap->leaveby, 'return', 'getops on object with spec okay' );
|
||||
is( $trap->stdout, '', 'Expecting no STDOUT' );
|
||||
is( $trap->stderr, '', 'Expecting no STDERR' );
|
||||
is( $trap->die, undef, 'Expecting no die message' );
|
||||
}
|
||||
|
||||
@ARGV = ( '--rows', 5, '--cols', 10 );
|
||||
$getopts = App::ClusterSSH::Getopt->new( parent => $mock_object, );
|
||||
trap {
|
||||
$getopts->getopts;
|
||||
};
|
||||
|
||||
$trap->did_return(" ... returned");
|
||||
$trap->quiet(" ... quietly");
|
||||
is( $mock_object->{cols}, 10, 'cols set correctly' );
|
||||
is( $mock_object->{rows}, 5, 'rows set correctly' );
|
||||
|
||||
done_testing;
|
1017
t/10host.t
1017
t/10host.t
File diff suppressed because it is too large
Load diff
2
t/10host_ssh_include
Normal file
2
t/10host_ssh_include
Normal file
|
@ -0,0 +1,2 @@
|
|||
include 10host_ssh_config
|
||||
host server_ssh_included
|
139
t/15config.t
139
t/15config.t
|
@ -1,13 +1,24 @@
|
|||
use strict;
|
||||
use warnings;
|
||||
|
||||
# Force use of English in tests for the moment, for those users that
|
||||
# have a different locale set, since errors are hardcoded below
|
||||
use POSIX qw(setlocale locale_h);
|
||||
setlocale( LC_ALL, "C" );
|
||||
|
||||
use FindBin qw($Bin $Script);
|
||||
use lib "$Bin/../lib";
|
||||
|
||||
# fix path for finding our fake xterm on headless systems that do
|
||||
# not have it installed, such as TravisCI via github
|
||||
BEGIN {
|
||||
$ENV{PATH} = $ENV{PATH} . ':' . $Bin . '/bin';
|
||||
}
|
||||
|
||||
use Test::More;
|
||||
use Test::Trap;
|
||||
use File::Which qw(which);
|
||||
use File::Temp qw(tempdir);
|
||||
use File::Temp qw(tempdir);
|
||||
use Test::Differences;
|
||||
|
||||
use Readonly;
|
||||
|
@ -32,7 +43,7 @@ Readonly::Hash my %default_config => {
|
|||
terminal_size => "80x24",
|
||||
|
||||
use_hotkeys => "yes",
|
||||
key_quit => "Control-q",
|
||||
key_quit => "Alt-q",
|
||||
key_addhost => "Control-Shift-plus",
|
||||
key_clientname => "Alt-n",
|
||||
key_history => "Alt-h",
|
||||
|
@ -41,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,
|
||||
|
@ -71,9 +86,14 @@ Readonly::Hash my %default_config => {
|
|||
telnet_args => "",
|
||||
ssh => 'ssh',
|
||||
ssh_args => "",
|
||||
sftp => 'sftp',
|
||||
sftp_args => "",
|
||||
|
||||
extra_tag_file => "",
|
||||
extra_cluster_file => "",
|
||||
external_cluster_command => '',
|
||||
external_command_mode => '0600',
|
||||
external_command_pipe => '',
|
||||
|
||||
unmap_on_redraw => "no",
|
||||
|
||||
|
@ -81,9 +101,14 @@ Readonly::Hash my %default_config => {
|
|||
history_width => 40,
|
||||
history_height => 10,
|
||||
|
||||
hostname_override => '',
|
||||
|
||||
command => q{},
|
||||
command_pre => q{},
|
||||
command_post => q{},
|
||||
title => q{15CONFIG.T},
|
||||
comms => q{ssh},
|
||||
hide_menu => 0,
|
||||
max_host_menu_items => 30,
|
||||
|
||||
macros_enabled => 'yes',
|
||||
|
@ -92,20 +117,36 @@ 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,
|
||||
menu_host_autotearoff => 0,
|
||||
|
||||
unique_servers => 0,
|
||||
use_all_a_records => 0,
|
||||
use_natural_sort => 0,
|
||||
|
||||
send_menu_xml_file => $ENV{HOME} . '/.csshrc_send_menu',
|
||||
send_menu_xml_file => $ENV{HOME} . '/.clusterssh/send_menu',
|
||||
|
||||
# Debian #842965
|
||||
auto_wm_decoration_offsets => "no",
|
||||
|
||||
# other bits inheritted from App::ClusterSSH::Base
|
||||
debug => 0,
|
||||
lang => 'en',
|
||||
|
||||
lang => 'en',
|
||||
user => '',
|
||||
rows => -1,
|
||||
cols => -1,
|
||||
|
||||
fillscreen => 'no',
|
||||
};
|
||||
my %expected = %default_config;
|
||||
is_deeply( $config, \%expected, 'default config is correct' );
|
||||
|
@ -164,6 +205,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, );
|
||||
};
|
||||
|
@ -246,7 +290,7 @@ isa_ok( $config, "App::ClusterSSH::Config" );
|
|||
is( $trap->stdout, q{}, 'Expecting no STDOUT' );
|
||||
is( $trap->stderr, q{}, 'Expecting no STDERR' );
|
||||
is_deeply( $config, \%expected, 'amended config is correct' );
|
||||
is( $path, which('ls'), 'Found correct path to "ls"' );
|
||||
is( $path, 'ls', 'Found correct path to "ls"' );
|
||||
|
||||
# check for a binary already found
|
||||
my $newpath;
|
||||
|
@ -259,8 +303,8 @@ isa_ok( $config, "App::ClusterSSH::Config" );
|
|||
is( $trap->stdout, q{}, 'Expecting no STDOUT' );
|
||||
is( $trap->stderr, q{}, 'Expecting no STDERR' );
|
||||
is_deeply( $config, \%expected, 'amended config is correct' );
|
||||
is( $path, which('ls'), 'Found correct path to "ls"' );
|
||||
is( $path, $newpath, 'No change made from find_binary' );
|
||||
is( $path, 'ls', 'Found correct path to "ls"' );
|
||||
is( $path, $newpath, 'No change made from find_binary' );
|
||||
|
||||
# give false path to force another search
|
||||
trap {
|
||||
|
@ -272,8 +316,8 @@ isa_ok( $config, "App::ClusterSSH::Config" );
|
|||
is( $trap->stdout, q{}, 'Expecting no STDOUT' );
|
||||
is( $trap->stderr, q{}, 'Expecting no STDERR' );
|
||||
is_deeply( $config, \%expected, 'amended config is correct' );
|
||||
is( $path, which('ls'), 'Found correct path to "ls"' );
|
||||
is( $path, $newpath, 'No change made from find_binary' );
|
||||
is( $path, 'ls', 'Found correct path to "ls"' );
|
||||
is( $path, $newpath, 'No change made from find_binary' );
|
||||
|
||||
note('Checks on loading configs');
|
||||
note('empty dir');
|
||||
|
@ -304,6 +348,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();
|
||||
|
@ -371,9 +418,9 @@ is_deeply( $config, \%expected, 'amended config is correct' );
|
|||
|
||||
note('no .csshrc warning, .clusterssh dir plus config + extra config');
|
||||
open( $csshrc, '>', $ENV{HOME} . '/clusterssh.config' );
|
||||
print $csshrc 'terminal = something', $/;
|
||||
print $csshrc 'terminal_args = something', $/;
|
||||
close($csshrc);
|
||||
$expected{terminal} = 'something';
|
||||
$expected{terminal_args} = 'something';
|
||||
$config = App::ClusterSSH::Config->new();
|
||||
trap {
|
||||
$config->load_configs( $ENV{HOME} . '/clusterssh.config' );
|
||||
|
@ -463,7 +510,34 @@ is( $trap->stderr,
|
|||
'Expecting no STDERR'
|
||||
);
|
||||
|
||||
note('check failure to write default config is caught');
|
||||
SKIP: {
|
||||
skip "Test inappropriate when running as root", 5 if $< == 0;
|
||||
note('move of .csshrc failure');
|
||||
$ENV{HOME} = tempdir( CLEANUP => 1 );
|
||||
open( $csshrc, '>', $ENV{HOME} . '/.csshrc' );
|
||||
print $csshrc "Something", $/;
|
||||
close($csshrc);
|
||||
open( $csshrc, '>', $ENV{HOME} . '/.csshrc.DISABLED' );
|
||||
print $csshrc "Something else", $/;
|
||||
close($csshrc);
|
||||
chmod( 0666, $ENV{HOME} . '/.csshrc.DISABLED', $ENV{HOME} );
|
||||
$config = App::ClusterSSH::Config->new();
|
||||
trap {
|
||||
$config->write_user_config_file();
|
||||
};
|
||||
is( $trap->leaveby, 'die', 'died ok' );
|
||||
isa_ok( $config, "App::ClusterSSH::Config" );
|
||||
is( $trap->stdout, q{}, 'Expecting no STDOUT' );
|
||||
is( $trap->stderr, q{}, 'Expecting no STDERR' );
|
||||
is( $trap->die,
|
||||
q{Unable to create directory $HOME/.clusterssh: Permission denied}
|
||||
. $/,
|
||||
'Expected die msg ' . $trap->stderr
|
||||
);
|
||||
chmod( 0755, $ENV{HOME} . '/.csshrc.DISABLED', $ENV{HOME} );
|
||||
}
|
||||
|
||||
note('check failure to write default config is caught when loading config');
|
||||
$ENV{HOME} = tempdir( CLEANUP => 1 );
|
||||
mkdir( $ENV{HOME} . '/.clusterssh' );
|
||||
mkdir( $ENV{HOME} . '/.clusterssh/config' );
|
||||
|
@ -484,34 +558,56 @@ is( $trap->stderr,
|
|||
|
||||
note('Checking dump');
|
||||
$config = App::ClusterSSH::Config->new(
|
||||
send_menu_xml_file => $ENV{HOME} . '/.csshrc_send_menu' );
|
||||
send_menu_xml_file => $ENV{HOME} . '/.clusterssh/send_menu', );
|
||||
|
||||
trap {
|
||||
$config->dump();
|
||||
};
|
||||
my $expected = qq{# Configuration dump produced by "cssh -u"
|
||||
my $expected = qq{# Configuration dump produced by "cssh -d"
|
||||
auto_close=5
|
||||
auto_quit=yes
|
||||
auto_wm_decoration_offsets=no
|
||||
cols=-1
|
||||
command_post=
|
||||
command_pre=
|
||||
console=console
|
||||
console_args=
|
||||
console_position=
|
||||
debug=0
|
||||
external_cluster_command=
|
||||
external_command_mode=0600
|
||||
external_command_pipe=
|
||||
extra_cluster_file=
|
||||
extra_tag_file=
|
||||
fillscreen=no
|
||||
hide_menu=0
|
||||
history_height=10
|
||||
history_width=40
|
||||
hostname_override=
|
||||
key_addhost=Control-Shift-plus
|
||||
key_clientname=Alt-n
|
||||
key_history=Alt-h
|
||||
key_localname=Alt-l
|
||||
key_macros_enable=Alt-p
|
||||
key_paste=Control-v
|
||||
key_quit=Control-q
|
||||
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
|
||||
|
@ -520,13 +616,16 @@ max_host_menu_items=30
|
|||
menu_host_autotearoff=0
|
||||
menu_send_autotearoff=0
|
||||
mouse_paste=Button-2
|
||||
rows=-1
|
||||
rsh=rsh
|
||||
rsh_args=
|
||||
screen_reserve_bottom=60
|
||||
screen_reserve_left=0
|
||||
screen_reserve_right=0
|
||||
screen_reserve_top=0
|
||||
send_menu_xml_file=} . $ENV{HOME} . qq{/.csshrc_send_menu
|
||||
send_menu_xml_file=} . $ENV{HOME} . qq{/.clusterssh/send_menu
|
||||
sftp=sftp
|
||||
sftp_args=
|
||||
show_history=0
|
||||
ssh=ssh
|
||||
ssh_args=
|
||||
|
@ -546,9 +645,11 @@ terminal_reserve_right=0
|
|||
terminal_reserve_top=5
|
||||
terminal_size=80x24
|
||||
terminal_title_opt=-T
|
||||
unique_servers=0
|
||||
unmap_on_redraw=no
|
||||
use_all_a_records=0
|
||||
use_hotkeys=yes
|
||||
use_natural_sort=0
|
||||
#user=
|
||||
window_tiling=yes
|
||||
window_tiling_direction=right
|
||||
|
|
|
@ -5,6 +5,7 @@ command=
|
|||
comms=ssh
|
||||
console_position=
|
||||
extra_cluster_file=
|
||||
extra_tag_file=
|
||||
history_height=10
|
||||
history_width=40
|
||||
key_addhost=Control-Shift-plus
|
||||
|
@ -15,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
|
||||
|
|
96
t/20helper.t
96
t/20helper.t
|
@ -1,16 +1,31 @@
|
|||
use strict;
|
||||
use warnings;
|
||||
|
||||
# Force use of English in tests for the moment, for those users that
|
||||
# have a different locale set, since errors are hardcoded below
|
||||
use POSIX qw(setlocale locale_h);
|
||||
setlocale( LC_ALL, "C" );
|
||||
|
||||
use FindBin qw($Bin $Script);
|
||||
use lib "$Bin/../lib";
|
||||
|
||||
use Test::More;
|
||||
use Test::Trap;
|
||||
use File::Which qw(which);
|
||||
use File::Temp qw(tempdir);
|
||||
use File::Temp qw(tempdir);
|
||||
|
||||
use Readonly;
|
||||
|
||||
package App::ClusterSSH::Config;
|
||||
|
||||
sub new {
|
||||
my ( $class, %args ) = @_;
|
||||
my $self = {%args};
|
||||
return bless $self, $class;
|
||||
}
|
||||
|
||||
package main;
|
||||
|
||||
BEGIN {
|
||||
use_ok("App::ClusterSSH::Helper") || BAIL_OUT('failed to use module');
|
||||
}
|
||||
|
@ -20,18 +35,71 @@ my $helper;
|
|||
$helper = App::ClusterSSH::Helper->new();
|
||||
isa_ok( $helper, 'App::ClusterSSH::Helper' );
|
||||
|
||||
#note('check failure to write default config is caught');
|
||||
#$ENV{HOME} = tempdir( CLEANUP => 1 );
|
||||
#mkdir($ENV{HOME}.'/.clusterssh');
|
||||
#mkdir($ENV{HOME}.'/.clusterssh/config');
|
||||
#$config = App::ClusterSSH::Config->new();
|
||||
#trap {
|
||||
# $config->load_configs();
|
||||
#};
|
||||
#is( $trap->leaveby, 'return', 'returned ok' );
|
||||
#isa_ok( $config, "App::ClusterSSH::Config" );
|
||||
#isa_ok( $config, "App::ClusterSSH::Config" );
|
||||
#is( $trap->stdout, q{}, 'Expecting no STDOUT' );
|
||||
#is( $trap->stderr, q{Unable to write default $HOME/.clusterssh/config: Is a directory}.$/, 'Expecting no STDERR' );
|
||||
my $script;
|
||||
|
||||
trap {
|
||||
$script = $helper->script;
|
||||
};
|
||||
is( $trap->leaveby, 'die', 'returned ok' );
|
||||
is( $trap->stdout, q{}, 'Expecting no STDOUT' );
|
||||
is( $trap->stderr, q{}, 'Expecting no STDERR' );
|
||||
is( $trap->die, 'No configuration provided or in wrong format', 'no config' );
|
||||
|
||||
trap {
|
||||
$script = $helper->script( something => 'nothing' );
|
||||
};
|
||||
is( $trap->leaveby, 'die', 'returned ok' );
|
||||
is( $trap->stdout, q{}, 'Expecting no STDOUT' );
|
||||
is( $trap->stderr, q{}, 'Expecting no STDERR' );
|
||||
is( $trap->die, 'No configuration provided or in wrong format',
|
||||
'bad format' );
|
||||
|
||||
my $mock_config = App::ClusterSSH::Config->new();
|
||||
trap {
|
||||
$script = $helper->script($mock_config);
|
||||
};
|
||||
is( $trap->leaveby, 'die', 'returned ok' );
|
||||
is( $trap->stdout, q{}, 'Expecting no STDOUT' );
|
||||
|
||||
# ignore stderr here as it will complain about missing xxx_arg var
|
||||
#is( $trap->stderr, q{}, 'Expecting no STDERR' );
|
||||
is( $trap->die, q{Config 'comms' not provided}, 'missing arg' );
|
||||
|
||||
$mock_config->{comms} = 'method';
|
||||
trap {
|
||||
$script = $helper->script($mock_config);
|
||||
};
|
||||
is( $trap->leaveby, 'die', 'returned ok' );
|
||||
is( $trap->stdout, q{}, 'Expecting no STDOUT' );
|
||||
is( $trap->stderr, q{}, 'Expecting no STDERR' );
|
||||
is( $trap->die, q{Config 'method' not provided}, 'missing arg' );
|
||||
|
||||
$mock_config->{method} = 'binary';
|
||||
trap {
|
||||
$script = $helper->script($mock_config);
|
||||
};
|
||||
is( $trap->leaveby, 'die', 'returned ok' );
|
||||
is( $trap->stdout, q{}, 'Expecting no STDOUT' );
|
||||
is( $trap->stderr, q{}, 'Expecting no STDERR' );
|
||||
is( $trap->die, q{Config 'method_args' not provided}, 'missing arg' );
|
||||
|
||||
$mock_config->{method_args} = 'rubbish';
|
||||
$mock_config->{command} = 'echo';
|
||||
$mock_config->{auto_close} = 5;
|
||||
trap {
|
||||
$script = $helper->script($mock_config);
|
||||
};
|
||||
is( $trap->leaveby, 'return', 'returned ok' );
|
||||
is( $trap->stdout, q{}, 'Expecting no STDOUT' );
|
||||
is( $trap->stderr, q{}, 'Expecting no STDERR' );
|
||||
is( $trap->die, undef, 'not died' );
|
||||
|
||||
trap {
|
||||
eval {$script};
|
||||
};
|
||||
is( $trap->leaveby, 'return', 'returned ok' );
|
||||
is( $trap->stdout, q{}, 'Expecting no STDOUT' );
|
||||
is( $trap->stderr, q{}, 'Expecting no STDERR' );
|
||||
is( $trap->die, undef, 'not died' );
|
||||
|
||||
done_testing();
|
||||
|
|
258
t/30cluster.t
258
t/30cluster.t
|
@ -1,22 +1,64 @@
|
|||
use strict;
|
||||
use warnings;
|
||||
|
||||
# Force use of English in tests for the moment, for those users that
|
||||
# have a different locale set, since errors are hardcoded below
|
||||
use POSIX qw(setlocale locale_h);
|
||||
setlocale( LC_ALL, "C" );
|
||||
|
||||
use FindBin qw($Bin $Script);
|
||||
use lib "$Bin/../lib";
|
||||
|
||||
use Test::More;
|
||||
use Test::Trap;
|
||||
use File::Which qw(which);
|
||||
use File::Temp qw(tempdir);
|
||||
use English '-no_match_vars';
|
||||
|
||||
use Readonly;
|
||||
|
||||
BEGIN {
|
||||
use_ok("App::ClusterSSH::Cluster") || BAIL_OUT('failed to use module');
|
||||
package Test::ClusterSSH::Mock;
|
||||
|
||||
# generate purpose object used to simplfy testing
|
||||
|
||||
sub new {
|
||||
my ( $class, %args ) = @_;
|
||||
my $config = {%args};
|
||||
return bless $config, $class;
|
||||
}
|
||||
|
||||
my $cluster1 = App::ClusterSSH::Cluster->new();
|
||||
sub parent {
|
||||
my ($self) = @_;
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub config {
|
||||
my ($self) = @_;
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub load_configs {
|
||||
my ($self) = @_;
|
||||
return $self;
|
||||
}
|
||||
|
||||
sub config_file {
|
||||
my ($self) = @_;
|
||||
return {};
|
||||
}
|
||||
|
||||
1;
|
||||
|
||||
package main;
|
||||
|
||||
BEGIN {
|
||||
$ENV{PATH} = $ENV{PATH} . ':' . $Bin . '/bin';
|
||||
use_ok("App::ClusterSSH::Cluster") || BAIL_OUT('failed to use module');
|
||||
use_ok("App::ClusterSSH::Config") || BAIL_OUT('failed to use module');
|
||||
}
|
||||
|
||||
my $mock_object = Test::ClusterSSH::Mock->new();
|
||||
|
||||
my $cluster1 = App::ClusterSSH::Cluster->new( parent => $mock_object );
|
||||
isa_ok( $cluster1, 'App::ClusterSSH::Cluster' );
|
||||
|
||||
my $cluster2 = App::ClusterSSH::Cluster->new();
|
||||
|
@ -42,21 +84,23 @@ isa_ok( $cluster1, 'App::ClusterSSH::Cluster' );
|
|||
|
||||
# no point running this test as root since root cannot be blocked
|
||||
# from accessing the file
|
||||
if ( $EUID != 0 ) {
|
||||
my $no_read = $Bin . '/30cluster.cannot_read';
|
||||
chmod 0000, $no_read;
|
||||
trap {
|
||||
$cluster1->read_cluster_file($no_read);
|
||||
};
|
||||
chmod 0644, $no_read;
|
||||
isa_ok( $trap->die, 'App::ClusterSSH::Exception::LoadFile' );
|
||||
is( $trap->die,
|
||||
"Unable to read file $no_read: Permission denied",
|
||||
'Error on reading an existing file ok'
|
||||
);
|
||||
}
|
||||
else {
|
||||
pass('Cannot test for lack of read access when run as root');
|
||||
TODO: {
|
||||
if ( $EUID != 0 ) {
|
||||
my $no_read = $Bin . '/30cluster.cannot_read';
|
||||
chmod 0000, $no_read;
|
||||
trap {
|
||||
$cluster1->read_cluster_file($no_read);
|
||||
};
|
||||
chmod 0644, $no_read;
|
||||
isa_ok( $trap->die, 'App::ClusterSSH::Exception::LoadFile' );
|
||||
is( $trap->die,
|
||||
"Unable to read file $no_read: Permission denied",
|
||||
'Error on reading an existing file ok'
|
||||
);
|
||||
}
|
||||
else {
|
||||
pass('Cannot test for lack of read access when run as root');
|
||||
}
|
||||
}
|
||||
|
||||
$expected{tag1} = ['host1'];
|
||||
|
@ -88,34 +132,82 @@ is( scalar $cluster1->get_tag('default'),
|
|||
'Count correct'
|
||||
);
|
||||
|
||||
my $tags;
|
||||
trap {
|
||||
$tags = $cluster1->get_tag('does_not_exist');
|
||||
};
|
||||
is( $trap->leaveby, 'return', 'non-existant tag returns correctly' );
|
||||
is( $trap->stdout, '', 'no stdout for non-existant get_tag' );
|
||||
is( $trap->stderr, '', 'no stderr for non-existant get_tag' );
|
||||
is( $tags, undef, 'non-existant tag returns undef' );
|
||||
|
||||
@default_expected
|
||||
= sort qw/ default people tag1 tag2 tag3 tag10 tag20 tag30 tag40 tag50 /;
|
||||
trap {
|
||||
@default = $cluster1->list_tags;
|
||||
};
|
||||
is( $trap->leaveby, 'return', 'list_tags returned okay' );
|
||||
is( $trap->stdout, '', 'no stdout for non-existant get_tag' );
|
||||
is( $trap->stderr, '', 'no stderr for non-existant get_tag' );
|
||||
is_deeply( \@default, \@default_expected, 'tag list correct' );
|
||||
|
||||
my $count;
|
||||
trap {
|
||||
$count = $cluster1->list_tags;
|
||||
};
|
||||
is( $trap->leaveby, 'return', 'list_tags returned okay' );
|
||||
is( $trap->stdout, '', 'no stdout for non-existant get_tag' );
|
||||
is( $trap->stderr, '', 'no stderr for non-existant get_tag' );
|
||||
is_deeply( $count, 10, 'tag list count correct' );
|
||||
|
||||
# now checks against running an external command
|
||||
|
||||
my @external_expected;
|
||||
|
||||
@external_expected
|
||||
= $cluster1->get_external_clusters("$Bin/external_cluster_command");
|
||||
# text fetching external clusters when no command set or runnable
|
||||
#$mock_object->{external_cluster_command} = '/tmp/doesnt_exist';
|
||||
trap {
|
||||
@external_expected = $cluster1->_run_external_clusters();
|
||||
};
|
||||
is( $trap->leaveby, 'return', 'non-existant tag returns correctly' );
|
||||
is( $trap->stdout, '', 'no stdout for non-existant get_tag' );
|
||||
is( $trap->stderr, '', 'no stderr for non-existant get_tag' );
|
||||
is( $tags, undef, 'non-existant tag returns undef' );
|
||||
@external_expected = $cluster1->list_external_clusters();
|
||||
is_deeply( \@external_expected, [], 'External command doesnt exist' );
|
||||
is( scalar $cluster1->list_external_clusters,
|
||||
0, 'External command failed tag count' );
|
||||
|
||||
$mock_object->{external_cluster_command} = "$Bin/external_cluster_command";
|
||||
|
||||
@external_expected = $cluster1->list_external_clusters();
|
||||
is_deeply(
|
||||
\@external_expected,
|
||||
[qw/ tag100 tag200 tag300 tag400 /],
|
||||
'External command no args'
|
||||
);
|
||||
is( scalar $cluster1->list_external_clusters,
|
||||
4, 'External command tag count' );
|
||||
|
||||
@external_expected = $cluster1->get_external_clusters();
|
||||
is_deeply( \@external_expected, [], 'External command no args' );
|
||||
|
||||
@external_expected = $cluster1->get_external_clusters(
|
||||
"$Bin/external_cluster_command tag1 tag2");
|
||||
@external_expected = $cluster1->get_external_clusters("tag1 tag2");
|
||||
is_deeply( \@external_expected, [qw/tag1 tag2 /],
|
||||
'External command: 2 args passed through' );
|
||||
|
||||
@external_expected = $cluster1->get_external_clusters(
|
||||
"$Bin/external_cluster_command tag100");
|
||||
@external_expected = $cluster1->get_external_clusters("tag100");
|
||||
is_deeply( \@external_expected, [qw/host100 /],
|
||||
'External command: 1 tag expanded to one host' );
|
||||
|
||||
@external_expected = $cluster1->get_external_clusters(
|
||||
"$Bin/external_cluster_command tag200");
|
||||
@external_expected = $cluster1->get_external_clusters("tag200");
|
||||
is_deeply(
|
||||
\@external_expected,
|
||||
[qw/host200 host205 host210 /],
|
||||
'External command: 1 tag expanded to 3 hosts and sorted'
|
||||
);
|
||||
|
||||
@external_expected = $cluster1->get_external_clusters(
|
||||
"$Bin/external_cluster_command tag400");
|
||||
@external_expected = $cluster1->get_external_clusters("tag400");
|
||||
is_deeply(
|
||||
\@external_expected,
|
||||
[ qw/host100 host200 host205 host210 host300 host325 host350 host400 host401 /
|
||||
|
@ -134,8 +226,7 @@ if ( $ENV{TEST_VERBOSE} ) {
|
|||
}
|
||||
|
||||
trap {
|
||||
@external_expected = $cluster1->get_external_clusters(
|
||||
"$Bin/external_cluster_command -x $redirect");
|
||||
@external_expected = $cluster1->get_external_clusters("-x $redirect");
|
||||
};
|
||||
like(
|
||||
$trap->die,
|
||||
|
@ -146,8 +237,7 @@ is( $trap->stdout, '', 'External command: no stdout from perl code' );
|
|||
is( $trap->stderr, '', 'External command: no stderr from perl code' );
|
||||
|
||||
trap {
|
||||
@external_expected = $cluster1->get_external_clusters(
|
||||
"$Bin/external_cluster_command -q $redirect");
|
||||
@external_expected = $cluster1->get_external_clusters("-q $redirect");
|
||||
};
|
||||
like(
|
||||
$trap->die,
|
||||
|
@ -157,6 +247,108 @@ like(
|
|||
is( $trap->stdout, '', 'External command: no stdout from perl code' );
|
||||
is( $trap->stderr, '', 'External command: no stderr from perl code' );
|
||||
|
||||
# check reading of cluster files
|
||||
trap {
|
||||
$cluster1->get_cluster_entries( $Bin . '/30cluster.file3' );
|
||||
};
|
||||
is( $trap->leaveby, 'return', 'exit okay on get_cluster_entries' );
|
||||
is( $trap->stdout, '', 'no stdout for get_cluster_entries' );
|
||||
is( $trap->stderr, '', 'no stderr for get_cluster_entries' );
|
||||
|
||||
# check reading of tag files
|
||||
trap {
|
||||
$cluster1->get_tag_entries( $Bin . '/30cluster.tag1' );
|
||||
};
|
||||
is( $trap->leaveby, 'return', 'exit okay on get_tag_entries' );
|
||||
is( $trap->stdout, '', 'no stdout for get_tag_entries' );
|
||||
is( $trap->stderr, '', 'no stderr for get_tag_entries' );
|
||||
|
||||
# This step is required for using find_binary within the underlying
|
||||
# code of the following methods
|
||||
$cluster1->set_config( App::ClusterSSH::Config->new() );
|
||||
|
||||
# test bash expansion
|
||||
my @expected = ( 'aa', 'ab', 'ac' );
|
||||
$cluster1->register_tag( 'glob1', 'a{a,b,c}' );
|
||||
@got = $cluster2->get_tag('glob1');
|
||||
is_deeply( \@got, \@expected, 'glob1 expansion, words' )
|
||||
or diag explain @got;
|
||||
|
||||
@expected = ( 'ax', 'ay', 'az' );
|
||||
$cluster1->register_tag( 'glob2', 'a{x..z}' );
|
||||
@got = $cluster2->get_tag('glob2');
|
||||
is_deeply( \@got, \@expected, 'glob2 expansion, words' )
|
||||
or diag explain @got;
|
||||
|
||||
@expected = ( 'b1', 'b2', 'b3' );
|
||||
$cluster1->register_tag( 'glob3', 'b{1..3}' );
|
||||
@got = $cluster2->get_tag('glob3');
|
||||
is_deeply( \@got, \@expected, 'glob3 expansion, number range' )
|
||||
or diag explain @got;
|
||||
|
||||
@expected = ( 'ca', 'cb', 'cc', 'd7', 'd8', 'd9' );
|
||||
$cluster1->register_tag( 'glob4', 'c{a..c}', 'd{7..9}' );
|
||||
@got = $cluster2->get_tag('glob4');
|
||||
is_deeply( \@got, \@expected, 'glob4 expansion, mixed' )
|
||||
or diag explain @got;
|
||||
|
||||
# make sure reasonable expansions get through with no nasty metachars
|
||||
# This one does not work due to the way File::Glob works
|
||||
#@expected = ( 'cd..f}', 'c{a..c' );
|
||||
@expected = ( 'c', 'cd..f}' );
|
||||
$cluster1->register_tag( 'glob5', 'c{a..c', 'cd..f}' );
|
||||
@got = $cluster2->get_tag('glob5');
|
||||
is_deeply( \@got, \@expected, 'glob5 expansion, mixed' )
|
||||
or diag explain @got;
|
||||
|
||||
@expected = ();
|
||||
trap {
|
||||
$cluster1->register_tag( 'glob6', 'c{a..c} ; echo NASTY' );
|
||||
};
|
||||
is( $trap->leaveby, 'return', 'didnt die on nasty chars' );
|
||||
is( $trap->die, undef, 'didnt die on nasty chars' );
|
||||
is( $trap->stdout, q{}, 'Expecting no STDOUT' );
|
||||
like(
|
||||
$trap->stderr,
|
||||
qr/Bad characters picked up in tag 'glob6':.*/,
|
||||
'warned on nasty chars'
|
||||
);
|
||||
@got = $cluster2->get_tag('glob6');
|
||||
is_deeply( \@got, \@expected, 'glob6 expansion, nasty chars' )
|
||||
or diag explain @got;
|
||||
|
||||
@expected = ();
|
||||
trap {
|
||||
$cluster1->register_tag( 'glob7', 'c{a..b} `echo NASTY`' );
|
||||
};
|
||||
is( $trap->leaveby, 'return', 'didnt die on nasty chars' );
|
||||
is( $trap->die, undef, 'didnt die on nasty chars' );
|
||||
is( $trap->stdout, q{}, 'Expecting no STDOUT' );
|
||||
like(
|
||||
$trap->stderr,
|
||||
qr/Bad characters picked up in tag 'glob7':.*/,
|
||||
'warned on nasty chars'
|
||||
);
|
||||
@got = $cluster2->get_tag('glob7');
|
||||
is_deeply( \@got, \@expected, 'glob7 expansion, nasty chars' )
|
||||
or diag explain @got;
|
||||
|
||||
@expected = ();
|
||||
trap {
|
||||
$cluster1->register_tag( 'glob8', 'c{a..b} $!', );
|
||||
};
|
||||
is( $trap->leaveby, 'return', 'didnt die on nasty chars' );
|
||||
is( $trap->die, undef, 'didnt die on nasty chars' );
|
||||
is( $trap->stdout, q{}, 'Expecting no STDOUT' );
|
||||
like(
|
||||
$trap->stderr,
|
||||
qr/Bad characters picked up in tag 'glob8':.*/,
|
||||
'warned on nasty chars'
|
||||
);
|
||||
@got = $cluster2->get_tag('glob8');
|
||||
is_deeply( \@got, \@expected, 'glob8 expansion, nasty chars' )
|
||||
or diag explain @got;
|
||||
|
||||
done_testing();
|
||||
|
||||
sub test_expected {
|
||||
|
|
|
@ -1,9 +1,20 @@
|
|||
use strict;
|
||||
use warnings;
|
||||
|
||||
# Force use of English in tests for the moment, for those users that
|
||||
# have a different locale set, since errors are hardcoded below
|
||||
use POSIX qw(setlocale locale_h);
|
||||
setlocale( LC_ALL, "C" );
|
||||
|
||||
use FindBin qw($Bin $Script);
|
||||
use lib "$Bin/../lib";
|
||||
|
||||
# fix path for finding our fake xterm on headless systems that do
|
||||
# not have it installed, such as TravisCI via github
|
||||
BEGIN {
|
||||
$ENV{PATH} = $ENV{PATH} . ':' . $Bin . '/bin';
|
||||
}
|
||||
|
||||
use Test::More;
|
||||
use Test::Trap;
|
||||
use File::Which qw(which);
|
||||
|
@ -18,4 +29,24 @@ $app = App::ClusterSSH->new();
|
|||
isa_ok( $app, 'App::ClusterSSH' );
|
||||
isa_ok( $app->config, 'App::ClusterSSH::Config' );
|
||||
|
||||
for my $submod (qw/ cluster helper options window /) {
|
||||
trap {
|
||||
$app->$submod;
|
||||
};
|
||||
$trap->quiet("$submod loaded okay");
|
||||
}
|
||||
|
||||
trap {
|
||||
$app->exit_prog;
|
||||
};
|
||||
$trap->quiet("No errors from exit_prog call");
|
||||
|
||||
my @provided = (qw/ one one one two two three four four four /);
|
||||
my @expected = sort (qw/ one two three four /);
|
||||
my @got;
|
||||
trap {
|
||||
@got = sort $app->remove_repeated_servers(@provided);
|
||||
};
|
||||
is_deeply( \@got, \@expected, "Repeated servers removed okay" );
|
||||
|
||||
done_testing();
|
||||
|
|
8
t/bin/xterm
Executable file
8
t/bin/xterm
Executable file
|
@ -0,0 +1,8 @@
|
|||
#!/usr/bin/env perl
|
||||
|
||||
# small 'fake' script to allow xterm to be found when performing tests
|
||||
# on systems that do not have it
|
||||
|
||||
warn "$_=$ENV{$_}", $/ for ( sort keys %ENV ) if ( $ENV{TEST_VERBOSE} );
|
||||
|
||||
exit 0
|
9
t/changes.t
Normal file
9
t/changes.t
Normal file
|
@ -0,0 +1,9 @@
|
|||
use Test::More;
|
||||
|
||||
unless ( $ENV{RELEASE_TESTING} ) {
|
||||
plan( skip_all => "Author tests not required for installation" );
|
||||
}
|
||||
|
||||
eval 'use Test::CPAN::Changes';
|
||||
plan skip_all => 'Test::CPAN::Changes required for this test' if $@;
|
||||
changes_ok();
|
|
@ -1,4 +1,4 @@
|
|||
#!/usr/bin/perl
|
||||
#!/usr/bin/env perl
|
||||
#
|
||||
# test script for proving external command for fetching tags works
|
||||
#
|
||||
|
@ -7,7 +7,14 @@ use warnings;
|
|||
use Getopt::Std;
|
||||
|
||||
my $opt = {};
|
||||
getopts( 'qx', $opt );
|
||||
getopts( 'Lqx', $opt );
|
||||
|
||||
my %tag_lookup = (
|
||||
tag100 => [qw/ host100 /],
|
||||
tag200 => [qw/ host200 host210 host205 /],
|
||||
tag300 => [qw/ host300 host350 host325 /],
|
||||
tag400 => [qw/ tag100 tag200 tag300 host400 host401 /],
|
||||
);
|
||||
|
||||
# if we get '-q' option, force an error
|
||||
if ( $opt->{q} ) {
|
||||
|
@ -21,12 +28,11 @@ if ( $opt->{x} ) {
|
|||
exit 5;
|
||||
}
|
||||
|
||||
my %tag_lookup = (
|
||||
tag100 => [qw/ host100 /],
|
||||
tag200 => [qw/ host200 host210 host205 /],
|
||||
tag300 => [qw/ host300 host350 host325 /],
|
||||
tag400 => [qw/ tag100 tag200 tag300 host400 host401 /],
|
||||
);
|
||||
# '-L' means list out available tags
|
||||
if ( $opt->{L} ) {
|
||||
print join( ' ', sort keys %tag_lookup ), $/;
|
||||
exit 0;
|
||||
}
|
||||
|
||||
my @lookup = @ARGV;
|
||||
|
||||
|
|
11
t/manifest.t
11
t/manifest.t
|
@ -1,11 +0,0 @@
|
|||
use Test::More;
|
||||
|
||||
# This is the common idiom for author test modules like this, but see
|
||||
# the full example in examples/checkmanifest.t and, more importantly,
|
||||
# Adam Kennedy's article: http://use.perl.org/~Alias/journal/38822
|
||||
eval 'use Test::DistManifest';
|
||||
if ($@) {
|
||||
plan skip_all => 'Test::DistManifest required to test MANIFEST';
|
||||
}
|
||||
|
||||
manifest_ok( 'MANIFEST', 'MANIFEST.SKIP' );
|
4
t/perltidyrc
Normal file
4
t/perltidyrc
Normal file
|
@ -0,0 +1,4 @@
|
|||
# perltidy to Perl Best Practices standard
|
||||
-pbp -nst -nse
|
||||
## For use in ~/.perltidyrc
|
||||
# --backup-and-modify-in-place
|
|
@ -2,18 +2,10 @@ use strict;
|
|||
use warnings;
|
||||
use Test::More;
|
||||
|
||||
# Ensure a recent version of Test::Pod::Coverage
|
||||
my $min_tpc = 1.08;
|
||||
eval "use Test::Pod::Coverage $min_tpc";
|
||||
plan skip_all =>
|
||||
"Test::Pod::Coverage $min_tpc required for testing POD coverage"
|
||||
eval "use Test::Pod::Coverage 1.00";
|
||||
plan skip_all => "Test::Pod::Coverage 1.00 required for testing POD coverage"
|
||||
if $@;
|
||||
|
||||
# Test::Pod::Coverage doesn't require a minimum Pod::Coverage version,
|
||||
# but older versions don't recognize some common documentation styles
|
||||
my $min_pc = 0.18;
|
||||
eval "use Pod::Coverage $min_pc";
|
||||
plan skip_all => "Pod::Coverage $min_pc required for testing POD coverage"
|
||||
if $@;
|
||||
plan skip_all => "Skipping coverage tests" unless $ENV{COVERAGE};
|
||||
|
||||
all_pod_coverage_ok();
|
||||
|
|
87
t/range.t
Normal file
87
t/range.t
Normal file
|
@ -0,0 +1,87 @@
|
|||
#!/usr/bin/env perl
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use FindBin qw($Bin);
|
||||
use lib "$Bin/../lib";
|
||||
|
||||
use Test::More;
|
||||
use Test::Trap;
|
||||
use Data::Dump;
|
||||
|
||||
require_ok('App::ClusterSSH::Range')
|
||||
|| BAIL_OUT('Failed to use App::ClusterSSH::Range');
|
||||
|
||||
my %tests = (
|
||||
'a' => 'a',
|
||||
'c{a,b}' => 'ca cb',
|
||||
'd{a,b,c}' => 'da db dc',
|
||||
'e{0}' => 'e0',
|
||||
'f{0..3}' => 'f0 f1 f2 f3',
|
||||
'g{0..2,4}' => 'g0 g1 g2 g4',
|
||||
'h{0..2,4..6}' => 'h0 h1 h2 h4 h5 h6',
|
||||
'i{0..1,a}' => 'i0 i1 ia',
|
||||
'j{0..2,a,b,c}' => 'j0 j1 j2 ja jb jc',
|
||||
'k{4..6,a..c}' => 'k4 k5 k6 ka kb kc',
|
||||
'l{0..2,7..9,e..g}' => 'l0 l1 l2 l7 l8 l9 le lf lg',
|
||||
'm{0,1}' => 'm0 m1',
|
||||
'n0..2}' => 'n0..2}',
|
||||
'host{a,b}-test{1,2}' =>
|
||||
'hosta-test1 hosta-test2 hostb-test1 hostb-test2',
|
||||
|
||||
# NOTE: the following are not "as expected" in line with above tests
|
||||
# due to bsd_glob functionality. See output from:
|
||||
# print join(q{ }, bsd_glob("o{a,b,c")).$/
|
||||
'o{a,b,c' => 'o',
|
||||
'p{0..2' => 'p',
|
||||
|
||||
# Reported as bug in github issue #89
|
||||
'q-0{0,1}' => 'q-00 q-01',
|
||||
'q-0{0..1}' => 'q-00 q-01',
|
||||
|
||||
# expand pure ranges
|
||||
'{10..12}' => '10 11 12',
|
||||
|
||||
# expand ports
|
||||
'lh:{22001..22003}' => 'lh:22001 lh:22002 lh:22003',
|
||||
|
||||
# FQDN's
|
||||
'lh{1..3}.dot.com' => 'lh1.dot.com lh2.dot.com lh3.dot.com',
|
||||
|
||||
# IP addresses
|
||||
'127.0.0.{10..12}' => '127.0.0.10 127.0.0.11 127.0.0.12',
|
||||
'127.0.{20..22}.1' => '127.0.20.1 127.0.21.1 127.0.22.1',
|
||||
);
|
||||
|
||||
my $range = App::ClusterSSH::Range->new();
|
||||
isa_ok( $range, 'App::ClusterSSH::Range', 'object created correctly' );
|
||||
|
||||
for my $key ( sort keys %tests ) {
|
||||
my $expected = $tests{$key};
|
||||
my @expected = split / /, $tests{$key};
|
||||
|
||||
my $got;
|
||||
trap {
|
||||
$got = $range->expand($key);
|
||||
};
|
||||
|
||||
is( $trap->stdout, '', "No stdout for scalar $key" );
|
||||
is( $trap->stderr, '', "No stderr for scalar $key" );
|
||||
is( $trap->leaveby, 'return', "correct leaveby for scalar $key" );
|
||||
is( $trap->die, undef, "die is undef for scalar $key" );
|
||||
is( $got, "$expected", "expected return for scalar $key" );
|
||||
|
||||
my @got;
|
||||
trap {
|
||||
@got = $range->expand($key);
|
||||
};
|
||||
|
||||
is( $trap->stdout, '', "No stdout for array $key" );
|
||||
is( $trap->stderr, '', "No stderr for array $key" );
|
||||
is( $trap->leaveby, 'return', "correct leaveby for array $key" );
|
||||
is( $trap->die, undef, "die is undef for array $key" );
|
||||
is_deeply( \@got, \@expected, "expected return for array $key" )
|
||||
|| diag explain \@got;
|
||||
}
|
||||
|
||||
done_testing();
|
Loading…
Add table
Add a link
Reference in a new issue