
Des codes sources perlConsultez toutes les FAQ
Nombre d'auteurs : 13, nombre de questions : 59, dernière mise à jour : 27 mai 2011
Sommaire
→
Réseaux- Comment connaitre le nom et l'ip d'une machine en perl ?
- Comment connaitre le pid du script perl en cours ?
- Comment connaitre le système d'exploitation de ma machine ?
- Comment déterminer l'espace des disques ?
- Comment lancer des commandes sur un serveur distant depuis Windows ?
- Comment se connecter via SSH sur des périphériques CISCO ?
Pas de secret, le CPAN contient ce qu'il faut. Utilisez les modules Sys::HostnameSys::Hostname et SocketSocket déjà présent dans le CORE de perl.
Pour connaitre le pid du script perl en cours, il suffit d'utiliser la variable spéciale perl $$. Ainsi, faite ceci :
Vous pouvez soit afficher une variable spéciale perl $^O ou bien afficher le contenu de la variable d'environnement %ENV. Voici un exemple de script affichant les deux façon d'obtenir le résultat voulu.
#!/usr/bin/perl
use strict;
use warnings;
my $sys_expl = $^O;
print "Voici mon OS : $sys_expl\n"; # => Voici mon OS : MSwin32
sous Windows : mMSwin32
sous Linux : linux
sous MAC : darwin
ou
#!/usr/bin/perl
use strict;
use warnings;
#Pour information
foreach my $nom_cle (keys %ENV) {
print "$nom_cle : $ENV{$nom_cle}\n";
}
# En ce qui nous interesse
print "Voici mon OS : $ENV{OS}\n"; # Voici mon OS : Windows_NT
Vous pouvez constatez que le résultat nous indique bien qu'on est sous windows. Mais les deux sont légèrement différents. Néanmoins, $^O donnera toujours le même résultat.
Pour connaitre l'espace disque restant du C:/, D:/ ou sous linux du /, ... Il existe un module Perl, Filesys::DfPortableFilesys::DfPortable.
#!/usr/bin/perl
use strict;
use warnings;
use Filesys::DfPortable;
my $Disque = 'C:/'; # ou même / par exemple
my $ref = dfportable($Disque);
if( defined($ref) ) {
print"Total bytes: $ref->{blocks}\n";
print"Total bytes free: $ref->{bfree}\n";
print"Total bytes avail to me: $ref->{bavail}\n";
print"Total bytes used: $ref->{bused}\n";
print"Percent full: $ref->{per}\n"
}
Cet exemple vous donnera la taille en octets. Si vous souhatez la taille en ko, Mo ou plus, il vous suffit de fournir un deuxième arguement.
#!/usr/bin/perl
use strict;
use warnings;
use Filesys::DfPortable;
my $Disque = 'C:/'; # ou même / par exemple
my $FormatSortie = 1024*1024*1024;
my $ref = dfportable($Disque, $FormatSortie);
if( defined($ref) ) {
print"Total bytes: $ref->{blocks}\n";
print"Total bytes free: $ref->{bfree}\n";
print"Total bytes avail to me: $ref->{bavail}\n";
print"Total bytes used: $ref->{bused}\n";
print"Percent full: $ref->{per}\n"
}
# Le résultat sera en Go.
Il peut être intéressant de se connecter sur un serveur distant Linux afin
de lancer des commandes telles (ls, perl toto.pl, etc) depuis un PC Windows.
De plus, l'idéal serait de transférer des fichiers depuis son PC Windows vers
un autre serveur ou l'inverse. Il est possible de faire cela depuis un
script Perl sans avoir besoin d'avoir cygwin, putty, ...
Voici une procédure utilisant le module
Net::SSH2Net::SSH2.
#========================================================
# But : Connection SSH + commandes (scp ou autre)
# Args : Reference d'un hash
# Retourne : rien
# Besoin : modules Net::SSH2
#==========================
sub CommandSSHFromWindows {
unless ( scalar(@_) == 1 ) {
my $usage = <<'FIN_USAGE';
Usage:
my %DataSSH = (
host => "IP serveur ou Host serveur",
login => "login",
password => "xxxxxx",
cmd => ["perl /home/toto/test.pl", "ls /usr"],
scp_put => [
[ "Fichier local", "Fichier destination"],
[ "Fichier local"], # Depot dans le rep courant du user
],
scp_get => [
[ "Fichier destination", "Fichier local"],
[ "Fichier destination"], # Depot dans le rep local courant
],
verbose => 1, # ou 0
);
CommandSSHFromWindows( \%DataSSH);
FIN_USAGE
die($usage);
}
my ($RefDataConnection) = @_;
$|++;
# parameters
my $host = $RefDataConnection->{host};
my $login = $RefDataConnection->{login};
my $password = $RefDataConnection->{password};
my $Refcmd = $RefDataConnection->{cmd};
my $Verbose = $RefDataConnection->{verbose} || 0;
require File::Basename;
require Net::SSH2;
my $ssh2 = Net::SSH2->new();
$ssh2->connect($host);
my ( $code, $error_name, $error_string ) = $ssh2->error();
if ($code) {
print "[WARNING] Unable to connect to host : $host\n\n";
return;
}
unless ( $ssh2->auth_password( $login, $password ) ) {
$ssh2->disconnect();
print "[WARNING] Unable to login.\n"
. "Check your login ($login) or your password\n\n";
return;
}
foreach my $cmd ( @{$Refcmd} ) {
if ( $Verbose == 1 ) {
print "\n- $cmd\n";
}
my $channel = $ssh2->channel();
$channel->blocking(1);
$channel->exec($cmd);
while ( $channel->read( my $buffer, 1024 ) ) {
if ( $Verbose == 1 ) {
print $buffer;
}
}
$channel->close;
}
# SCP si necessaire
# Put
if ( exists $RefDataConnection->{scp_put} ) {
foreach my $RefCoupleSCP_put ( @{ $RefDataConnection->{scp_put} } ) {
unless ( -e $RefCoupleSCP_put->[0] ) {
print "\n$RefCoupleSCP_put->[0] n'existe pas \n";
next;
}
my $message = "Transfert de $RefCoupleSCP_put->[0] vers $host";
if ( $Verbose == 1 ) {
print "\n$message ... ";
}
$ssh2->scp_put( $RefCoupleSCP_put->[0], $RefCoupleSCP_put->[1] )
or die $ssh2->error();
print "fini\n" if ( $Verbose == 1 );
}
}
# Get
if ( exists $RefDataConnection->{scp_get} ) {
foreach my $RefCoupleSCP_get ( @{ $RefDataConnection->{scp_get} } ) {
my $NomFichier = File::Basename::basename( $RefCoupleSCP_get->[0] );
if ( $Verbose == 1 ) {
}
$ssh2->scp_get( $RefCoupleSCP_get->[0], $RefCoupleSCP_get->[1] )
or die $ssh2->error();
print " : fini\n" if ( $Verbose == 1 );
}
}
$ssh2->disconnect();
return;
}
Pour l'utiliser, Il faut donner en argument une référence de hachage. Si vous souhaitez afficher les messages affichés sur la console du serveur distant, mettez verbose à 1.
#!/usr/bin/perl
use warnings;
use strict;
use Carp;
my %DataSSH = (
host => "Votre host",
login => "mon login",
password => "mon mot de passe",
cmd => [ "ls -alh /home/user", "perl toto.pl" ],
verbose => 1, # ou 0
);
CommandSSHFromWindows( \%DataSSH );
Si vous souhaitez envoyer un ou plusieurs fichiers sur le serveur distant, rajoutez dans le hachage la clé scp_put et/ou scp_get, exemple
scp_put => [
# Fichier local # fichier distant
[ "C:/Rep/path/monfichier sur mon disque", "/home/user/toto"],
[ "C:/Rep/path/monfichier2 sur mon disque"],
[ "C:/Rep/path/monfichier3 sur mon disque", "/home/user/monfichier3"],
#...
],
Voilà, si vous avez des questions, des remarques ou suggestions, c'est icicontribuez.
Ayant eu le problème moi même et constatant que c'est un problème récurrent sur Internet dont on ne trouve pas de vrais solutions, je vous propose la mienne. Pour SSH sur les périphériques Cisco beaucoup utilisent les modules Net::SSH::PerlNet::SSH::Perl, Perl::SSH2Perl::SSH2, voir même Net::Appliance::sessionNet::Appliance::session et aboutissent à des problèmes sur les périphériques Cisco du genre :
- Connexion SSH impossible
- Passage Enable impossible
- Impossible de lancer plusieurs commandes dans la même session ...
Donc après avoir tout essayé, je suis tombé sur le module Net::SSH::ExpectNet::SSH::Expect qui m'a permis d'obtenir une solution fonctionnelle en s'affranchissant des problèmes liés aux autres modules.
#!/usr/bin/perl
use strict;
use warnings;
use Net::SSH::Expect;
my $ssh = Net::SSH::Expect->new(
host => '192.168.90.100',
password => 'cisco',
user => 'admin',
raw_pty => 1
);
my $enable_passwd = "cisco";
my $login_output = $ssh->login();
$ssh->send("enable");
$ssh->waitfor( 'Password:\s*\z', 1 ) or die "prompt 'password' not found after 1 second";
$ssh->send($enable_passwd);
my $ls = $ssh->exec("show vlan");
print "$ls\n";
#Première façon de récupérer une sortie longue:
$ssh->send("show running-config");
while ( my $line = $ssh->read_line() ) {
print "$line\n";
}
#Deuxième façon (mais on récupère aussi les prompt avec cette méthode):
my @output = $ssh->exec("show running-config");
print @output;
$ssh->close();
Pour les problèmes de longueur de sortie sur le terminal (passage du --more-- sur les Cisco), il suffit d'exécuter la commande suivante avant votre commande :
$ssh->exec("terminal length 0");
et celle ci après votre commande afin de revenir dans l'état par défaut :
$ssh->exec("terminal length 24");
Bien sûr, les commandes "show vlan" et/ou "show running-config" sont là à titre indicatif, à remplacer par vos propres commandes ...
Voilà, si vous avez des questions, des remarques ou suggestions, c'est
icicontribuez.



