Предлагаю вашему вниманию скрипт, удобную менюшку, для удаленных сессий
по SSH и Telnet
Возможности:
- Автологин SSH и Telnet сессий
- Весьма не сложный в настройке конфиг
- Многоуровневое меню (поддерживаются суб-меню любой глубины)
- К любому суб-меню можно "приклеить ярлык" и обращаться на прямую к
этому меню из командной строки
- Одна железяка может иметь несколько ip адресов.
- Описания или заметки к каждой железке отображаются в меню
- Open Source
Зависимости:
libjson-xs-perl, libexpect-perl
Установка:
sudo apt-get install libjson-xs-perl libexpect-perl
копируем cm к примеру в /usr/local/bin
и даём бит исполняемый:
chmod +x /usr/local/bin/cm
создаем свой конфиг в /home/username/.cm
Использование:
cm [arg]
Немного предыстории:
Мне по долгу службы, приходиться часто лазить на удалённые железяки и
серверы по ssh.
Так как их приличное количество и запомнить все IP и хостнеймы просто не
возможно, было
решено написать простейшую менюшку на shell (скрипт авторизации написал
ещё давно).
Но копаться каждый раз в теле скрипта, для того чтобы добавить новую
железяку надоело.
Начали появляться железяки с уникальным логином/паролем (которые тоже
надо помнить).
В общем было решено написать нормальную менюшку на Perl. Где можно
указать логин/пароль
на конкретную железяку, делать суб-меню любой сложности. В общем чтобы
было удобно.
Под винду полно подобного софта - под линукс ничего подобного не видел.
Вопросы, комментарии приветствуются. Если окажется, что это нужно
кому-то кроме меня, будем развиваться ;)
Конфиг:
Конфиг в формате JSON. С первого взгляда может не понятен, но на самом
деле довольно прост.
Подробности можно узнать тут: http://ru.wikipedia.org/wiki/JSON
name - имя пункта меню
menu - при наличии этой опции означает, что это суб-меню
arg - передавая аргумент указанный здесь из командной строки, можно
сразу перейти на это суб-меню
ip - ip-адрес. Если этот пункт отсутствует, то пытается подключиться по
name. При наличии нескольких ip адресов, появляется меню с выбором
login - логин от железяки. Может использоваться без password для SSH сессий
password - пароль от железяки. Полезно для коммутаторов, маршрутизаторов
description - описание, заметка или что-то вроде того
type - если указан telnet, то подключаться будет по телнету
конфиг должен лежать в домашней директории:
~/.cm
Структура конфига очень напоминает хэши и массивы perl.
Примеры конфига:
1)--------------------------------------------------
[{
"name": "server1",
"ip": "192.168.11.9"
},
{
"name": "svn.corp",
"description": "SVN-Server"
},
{
"name": "Активное оборудование"
"arg": "a",
"menu": [{
"name": "Коммутаторы",
"menu": [{
"name": "192.168.11.2",
"login": "admin",
"password": "123456",
"type": "telnet"
},
{
"name": "192.168.11.3,
"login": "admin",
"password": "123456",
"type": "telnet"
}]
},
{
"name": "Маршрутизаторы",
"menu": [{
"name": "main",
"ip": "192.168.11.1"
}]
}]
}]
2)------------------------------------------------------------------------------------------
[{
"name": "Servers on VM",
"arg": "vm",
"menu": [{
"name": "SVN",
"ip": [
"192.168.4.9",
"98.33.74.2"
],
"login": "user44"
},
{
"name": "kvm.pika.corp",
"login": "root",
"description": "Hypervisor"
},
{
"name": "ngenix.r55.ru"
}]
},
{
"name": "Commutators & Routers",
"arg": "c",
"menu": [{
"name": "192.168.4.1",
"description": "Users GW",
"login": "admin",
"password": "1234secret"
},
{
"name": "192.168.1.10",
"login": "admin",
"password": "1234secret",
"type": "telnet"
},
{
"name": "E650-M9-AGG-10",
"ip": "10.10.3.9",
"description": [
"MSK-IX (4)",
"DATA-IX (2)"
],
"login": "support",
"password": "342r32r2ddd"
}]
}]
--
С уважением,
Alex Emergy
[{
"name": "Servers on VM",
"arg": "vm",
"menu": [{
"name": "SVN",
"ip": [
"192.168.4.9",
"98.33.74.2"
],
"login": "user44"
},
{
"name": "kvm.pika.corp",
"login": "root",
"description": "Hypervisor"
},
{
"name": "ngenix.r55.ru"
}]
},
{
"name": "Commutators & Routers",
"arg": "c",
"menu": [{
"name": "192.168.4.1",
"description": "Users GW",
"login": "admin",
"password": "1234secret"
},
{
"name": "192.168.1.10",
"login": "admin",
"password": "1234secret",
"type": "telnet"
},
{
"name": "E650-M9-AGG-10",
"ip": "10.10.3.9",
"description": [
"MSK-IX (4)",
"DATA-IX (2)"
],
"login": "support",
"password": "342r32r2ddd"
}]
}]
#!/usr/bin/perl
my $version = '1.0';
#===============================================================================
#
# FILE: connection-manager.pl
#
# USAGE: ./connection-manager.pl [-s] [arg]
#
# DESCRIPTION: Connection Manager
#
# AUTHOR: Alex Emergy
# CREATED: 21.04.2011 18:28:14
# DEPENDS: libjson-xs-perl, libexpect-perl
#
#===============================================================================
use strict;
use warnings;
use Data::Dumper;
use Expect;
use JSON::XS;
use Getopt::Std;
$Getopt::Std::STANDARD_HELP_VERSION = 1;
our ($opt_s);
getopts('s');
my $menu_file = $ENV{HOME} . "/.cm";
die "Файла конÑигÑÑаÑии $menu_file не
ÑÑÑеÑÑвÑеÑ!\n" unless (-e $menu_file);
# read menu file to $source_json
my $source_json;
open SRC, '<', $menu_file or die "Cannot open menu file: $!";
while (my $line = <SRC>) {
$source_json .= $line;
}
close(SRC);
# ARRAY from JSON
my $json_xs = JSON::XS->new();
my $config = $json_xs->decode($source_json);
die "Error in config" if ((!$config) or (ref($config) ne 'ARRAY'));
my $arg = shift(@ARGV);
$config = ck_arg($config, $config, $arg) if ($arg);
show_menu($config);
sub ck_arg {
my $json_obj = $_[0];
my $back = $_[1];
my $ARG = $_[2];
my $r;
foreach my $hash (@$json_obj) {
return $hash->{menu} if ($ARG eq $hash->{arg});
if ($hash->{menu}) {
$r = ck_arg($hash->{menu}, $back, $ARG);
return $r if ($r);
}
}
return $json_obj if ($back eq $json_obj);
}
sub show_menu {
my $change;
my $json_obj = $_[0];
LABEL:
my $count = 1;
system("clear");
foreach my $item (@$json_obj) {
my $estring = '';
$estring = "=>" if ($item->{menu});
$estring .= ArrayToString($item->{description}) if $item->{description};
$estring .= ArrayToString($item->{ip}) . "\n" if (($item->{ip}) and
($item->{ip} ne $item->{name}));
print "\033[1m" . $count . ") " . $item->{name} . "\033[0m " . $estring
. "\n";
$change->{$count} = $item->{name};
$count++;
}
$count--;
print "\n[1-$count] - ÐÑбоÑ, Enter - Ðазад/ÐÑÑ
од\n";
my $pick;
chomp($pick = <STDIN>);
return 0 if ($pick eq '');
goto LABEL unless (ck_valid_change($pick, $count));
ck_sub_menu($change->{$pick}, $json_obj);
goto LABEL;
}
sub ck_sub_menu {
my $change = $_[0];
my $json_obj = $_[1];
my $res;
system("clear");
foreach my $item (@$json_obj) {
if ($item->{name} eq $change) {
if ($item->{menu}) {
show_menu($item->{menu});
} else {
my $host;
unless ($item->{ip}) {
$host = $item->{name};
} else {
$host = $item->{ip};
}
connect_to($host, $item->{login}, $item->{password},
$item->{type});
}
}
}
return $res;
}
sub ip_sub_menu {
my $ips = $_[0];
my $menu;
foreach my $ip (@$ips) {
my $hash;
$hash->{'name'} = $ip;
$hash->{'ip'} = $ip;
$hash->{'ipmenu'} = "menu";
push(@$menu, $hash);
}
show_menu($menu);
}
sub connect_to {
my $ip = $_[0];
my $login = $_[1];
my $password = $_[2];
my $type = $_[3];
$type = 'ssh' unless($type);
if (ref($ip) eq 'ARRAY') {
ip_sub_menu($ip);
return 0;
}
unless($password) {
if ($type eq 'telnet') {
system("telnet $ip");
} else {
unless($login) {
system("ssh $ip");
} else {
system("ssh $login\@$ip");
}
}
} else {
my $timeout = 6;
my $exp = new Expect;
if ($type eq 'telnet') {
$exp->spawn("telnet $ip") or die "Cannot connect to address: $!\n";
} else {
$exp->spawn("ssh $login\@$ip") or die "Cannot connect to address:
$!\n";
}
$exp->expect($timeout,
[ "assword" => sub {
$exp->send("$password\n");
}],
[ "Are you sure you want to continue connecting" => sub {
$exp->send("yes\n");
exp_continue;
}],
[ "sername" => sub {
$exp->send("$login\n");
exp_continue;
}],
[ "ogin" => sub {
$exp->send("$login\n");
exp_continue;
}],
);
$exp->interact();
$exp->soft_close();
}
exit unless ($opt_s);
}
sub ArrayToString() {
my $string;
my $array = $_[0];
if (ref($array) eq 'ARRAY') {
foreach my $val (@$array) {
$string .= "\n\t" . $val;
}
$string =~ s/ *$//;
$string =~ s/^ //g;
return $string;
} else {
return "\n\t" . $array;
}
}
sub ck_valid_change {
my $change = $_[0];
my $char = $_[1];
my @chars = ( 1 .. $char );
my $yes = 0;
foreach my $res (@chars) {
$yes = 1 if ($res eq $change);
}
return $yes;
}
sub main::HELP_MESSAGE {
print <<EOF;
Usage: cm [-s] [menu arg]
-s - no exit
EOF
}
sub main::VERSION_MESSAGE {
print "Connection Manager version $version\n";
}
--
ubuntu-ru mailing list
ubuntu-ru@lists.ubuntu.com
https://lists.ubuntu.com/mailman/listinfo/ubuntu-ru