web-dev-qa-db-fra.com

Script Bash/Expect pour SSH

Je suis nouveau à attendre et scripting en général. J'essaie de créer quelques scripts pour me simplifier un peu la vie lorsque j'exécute les configurations de périphériques réseau. J'ai réussi à créer un script attendu de base sur SSH sur un périphérique et à enregistrer la configuration. 

Je souhaite approfondir cette question et permettre au script de se connecter à un certain nombre d'adresses IP au lieu d'une seule comme je l'ai maintenant. J'ai un fichier nommé list.txt avec quelques adresses IP différentes avec chaque adresse IP sur une ligne distincte.

Que devrais-je faire pour que le script expect se connecte à chacune de ces adresses IP et effectue le reste des tâches du script?

Voici le script Expect que j'ai jusqu'à présent:

#!/usr/bin/expect -f
#Tells interpreter where the expect program is located.  This may need adjusting according to
#your specific environment.  Type ' which expect ' (without quotes) at a command Prompt
#to find where it is located on your system and adjust the following line accordingly.
#
#
#Use the built in telnet program to connect to an IP and port number
spawn ssh 192.168.1.4 -l admin
#
#The first thing we should see is a User Name Prompt
#expect "login as:"
#
#Send a valid username to the device
#send "admin"
#
#The next thing we should see is a Password Prompt
expect "Password:"
#
#Send a vaild password to the device
send "password\n"
#
#If the device automatically assigns us to a priviledged level after successful logon,
#then we should be at an enable Prompt
expect "Last login:"
#
#Tell the device to turn off paging
#
#After each command issued at the enable Prompt, we expect the enable Prompt again to tell us the
#command has executed and is ready for another command
expect "admin@"
#
#Turn off the paging
send "set cli pager off\n"
#
#Show us the running configuration on the screen
send "show config running\n"
#
# Set the date.
set date [timestamp -format %C%y%m%d]
#
#Test output sent to file with a timestamp on end
#-noappend will create a new file if one already exists
log_file -noappend /home/test.cfg$date
#
expect "admin@"
#
#Exit out of the network device
send "exit\n"
# 
#The interact command is part of the expect script, which tells the script to hand off control to the user.
#This will allow you to continue to stay in the device for issuing future commands, instead of just closing
#the session after finishing running all the commands.`enter code here`
interact

Dois-je intégrer cela à un script Bash? Si tel est le cas, est-il possible de lire une ligne du fichier list.txt, de l'utiliser comme variable IP/hôte, puis de lire la suivante et de répéter?

6
minorix

Je ferais ceci (non testé):

#!/usr/bin/expect -f

set logfile "/home/text.cfg[clock format [clock seconds] -format %Y%m%d]"
close [open $logfile w]         ;# truncate the logfile if it exists

set ip_file "list.txt"
set fid [open $ip_file r]

while {[gets $fid ip] != -1} {

    spawn ssh $ip -l admin
    expect "Password:"
    send "password\r"

    expect "admin@"
    send "set cli pager off\r"

    log_file $logfile
    send "show config running\r"

    expect "admin@"
    log_file 

    send "exit\r"
    expect eof

}
close $fid

Remarques:

  • J'ai enlevé tous vos commentaires par souci de brièveté
  • utilisez \r pour simuler une frappe, entrez lorsque vous send commandes.
  • J'ai supposé que vous ne vouliez enregistrer que la sortie "show config running"
  • utilisez expect eof après avoir envoyé "exit"
2
glenn jackman

Ceci est une version Perl pour ce problème:

Instruction d'installation: cpan Expect

Ce script fonctionne parfaitement pour mes besoins.

Param 1: chaîne de connexion (ex: [email protected]) Param 2: mot de passe en texte clair Param 3: commande à exécuter

#!/usr/bin/Perl
use strict;

use Expect;

my $timeout=1;

my $command="ssh ".$ARGV[0]." ".$ARGV[2];

#print " => $command\n";

my $exp = Expect->spawn($command) or die "Cannot spawn $command: $!\n";
$exp->raw_pty(1);

LOGIN:
$exp->expect($timeout,
        [ 'ogin: $' => sub {
                     $exp->send("luser\n");         
                     exp_continue; }
        ],
    [ 'yes\/no\)\?\s*$' => sub {
              $exp->send("yes\n");
              goto LOGIN;
              }
    ],
        [ 'assword:\s*$' => sub {
                      $exp->send($ARGV[1]."\n");
            #print "password send : ", $ARGV[1];
                      exp_continue; }
        ],
        '-re', qr'[#>:] $'
);
$exp->soft_close();
1
jmrenouard

ou Utilisez set ip [gets stdin] à ip address depuis l'entrée de l'utilisateur.

par exemple-

met "Entrez votre adresse IP\n" set ip [get stdin]

utilisez ceci dans spawn, nous pouvons faire la même chose pour plusieurs adresses IP en utilisant loop - spawn ssh $ ip -l admin

0
Gunjan Srivastava

Une possibilité est de passer l'adresse IP en tant que paramètre dans votre script expect:

set Host_ip [lindex $argv 0]

puis créez un script Shell en appelant votre script prévu dans une boucle while:

ips_file="list.txt"

while read line
do
    your_expect_script line
done < $ips_file
0
andrade