Как ожидать тайм-аут при попытке войти в сеанс SSH, который он породил? - PullRequest
2 голосов
/ 10 августа 2011

Я пишу сценарий bash, который использует ожидаемый для входа в группу Cisco ASA (они не поддерживают вход в сертификат, следовательно, используют ожидаемый), вносит изменения в конфигурацию и затем выходит из системы.

Я бы хотел, чтобы скрипт перешел на следующую ASA, если он не может войти в систему.

Вот скрипт:

#!/bin/bash
# Scriptname: set-mtu
for asa in $(cat asa-list-temp)
do
        /usr/bin/expect << EndExpect
                spawn ssh admin_15@$asa
                expect "assword:"
                send "pa$$w0rd\r"
                expect ">"
                send "do something\r"
                expect ">"
                send "exit\r"
EndExpect
done

Я думаю, что могу установить таймаут на expect "assword:" но я не могу понять, как заставить его закрыть порожденную сессию ssh и затем перейти к следующему ASA в списке for.

Ответы [ 2 ]

4 голосов
/ 10 августа 2011

Прежде всего, я бы использовал для этого сценарий ожидаемого сценария и потерял бы сценарий bash.

Тогда для ожидаемой части: Вы можете сделать это, используя переключатель, который также соответствует тайм-ауту (страница 12 исследования ожидаемого). Таким образом, вы можете явно действовать, когда ожидаете тайм-ауты.

В противном случае, установив таймаут, он просто продолжит выполнение следующей команды в строке.

set timeout 60
expect {
 "assword:" {
 }
 timeout {
    exit 1 # to exit the expect part of the script
 }
}

Я создал нечто похожее, где я использовал общий сценарий ожидания для параллельного запуска сценария ожидания.

multiple.exp

#!/bin/sh
# the next line restarts using tclsh \
exec expect "$0" "$@"

# multiple.exp --
#
#    This file implements the running of multiple expect scripts in parallel.
#    It has some settings that can be found in multiple.config
#
# Copyright (c) 2008
#
# Author: Sander van Knippenberg

#####
# Setting the variables
##

source [file dirname $argv0]/.multiple.config

# To determine how long the script runs
set timingInfo("MultipleProcesses") [clock seconds]

# ---------------------------------------------------------------------

######
# Procedure to open a file with a certain filename and retrieve the contents as a string 
#
# Input: filename
# Output/Returns: content of the file
##
proc openFile {fileName} {
    if {[file exists $fileName] } {
        set input [open $fileName r]
    } else {
        puts stderr "fileToList cannot open $fileName"
        exit 1
    }
    set contents [read $input]
    close $input
    return $contents
}

######
# Procedure to write text to a file with the given filename
#
# Input: string, filename
##
proc toFile {text filename} {
    # Open the filename for writing
    set fileId [open $filename "w"]

    # Send the text to the file.
    # Failure to add '-nonewline' will reslt in an extra newline at the end of the file.
    puts -nonewline $fileId $text

    # Close the file, ensuring the data is written out before continueing with processing
    close $fileId
}

# ---------------------------------------------------------------------

# Check for the right argument
if {$argc > 0 } {
    set hostfile [lindex $argv 0]
} else {
    puts stderr "$argv0 --- usage: $argv0 <hosts file>"
    exit 1
}

# Create the commands that can be spawned in parallel
set commands {}

# Open the file with devices
set hosts [split [openFile $hostfile] "\n"]

foreach host $hosts {
        if { [string length $host] > 1 } {
            lappend commands "$commandDir/$commandName $host"  # Here you can enter your own command!
        }
}

#  Run the processes in parallel
set idlist {}
set runningcount 0
set pattern "This will never match I guess"

# Startup the first round of processes until maxSpawn is reached, 
# or the commands list is empty.
while { [llength $idlist] < $maxSpawn && [llength $commands] > 0} {
    set command [lindex $commands 0]
    eval spawn $command 
    lappend idlist $spawn_id
    set commands [lreplace $commands 0 0]
    incr runningcount
    set commandInfo($spawn_id) $command   
    set timingInfo($spawn_id) [clock seconds]
    send_user "      $commandInfo($spawn_id) - started\n"
}

# Finally start running the processes
while {$runningcount > 0} {
    expect {
        -i $idlist $pattern {
        }
        eof {
            set endedID $expect_out(spawn_id)
            set donepos [lsearch $idlist $endedID]
            set idlist [lreplace $idlist $donepos $donepos]
            incr runningcount -1
            set elapsedTime [clock format [expr [clock seconds] - $timingInfo($endedID)] -format "%M:%S (MM:SS)"]

            send_user "      $commandInfo($endedID) - finished in: $elapsedTime\n"

            # If there are more commands to execute then do it! 
            if {[llength $commands] > 0} {
                set command [lindex $commands 0]
                eval spawn $command             
                lappend idlist $spawn_id
                set commands [lreplace $commands 0 0]
                incr runningcount
                set commandInfo($spawn_id) $command            
                set timingInfo($spawn_id) [clock seconds]
           }
        }
        timeout {
            break
        }
    }
}
set elapsed_time [clock format [expr [clock seconds] - $timingInfo("MultipleProcesses")] -format "%M:%S (MM:SS)"] 
send_user "$argv0 $argc - finished in: $elapsedTime\n"

multiple.config

# The dir from where the commands are executed.
set commandDir "/home/username/scripts/expect/";
set commandName "somecommand.exp";

# The maximum number of simultanious spawned processes.
set maxSpawn 40;

# The maximum timeout in seconds before any of the processes should be finished in minutes
set timeout 20800;
0 голосов
/ 19 декабря 2014

Чтобы прояснить ответ: решение является типичным, просто сделайте обработку timeout в фигурной скобке expect.Итак, ваша Tcl / Expect часть в сценарии оболочки должна быть:

spawn ssh user@host
expect {
  "assword:" {
    send "password\r"
  }
  timeout {
    exit
  } 
}
expect "prompt>"
. . . 
   login success
. . .

Вот еще один пример , как ожидать / обработать timeout для возобновленияожидание строки результата, пока порожденная команда еще выполняется.

...