Des codes sources perlConsultez toutes les FAQ
Nombre d'auteurs : 13, nombre de questions : 59, dernière mise à jour : 27 mai 2011
- 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.