2014-10-02 47 views
1

我正在尝试用一些嵌入式Expect脚本编写一个小型bash脚本。我需要更换大约3500台交换机的主机名。我有一个带有我的IP地址和新主机名的csv文件,以及我的期望脚本。如果连接到交换机没有问题,脚本似乎运行得很好。如果我从交换机获得“超时”或“拒绝访问”,脚本将停止退出。我需要脚本去下一个IP地址。如果一个登录失败,期望脚本停止多个设备

我确实使用rancid clogin进行自动登录。

我是新来的期待和bash,并搜索我最好的朋友“谷歌”可能的答案,但无法找到答案。

该脚本如下:

hostnames.exp

#!/usr/bin/expect -f 
# Set variables 
set DATE [exec date +%F] 
set timeout 10 
# Log results 
log_file -a hostnames-$DATE.log 

# Let's go to configure mode 

## Read the file 
set fid [open ./hostnames.csv] 
set content [read $fid] 
close $fid 

## Split into records on newlines 
set records [split $content "\n"] 

## Iterate over the records 
foreach rec $records { 

## Split into fields on comma 
set fields [split $rec ","] 

## Assign fields to variables and print some out... 
lassign $fields\ hostname newname 

puts "$hostname" 
puts "$newname" 

if {$hostname == ""} continue 


# Announce which device we are working on and at what time 
send_user "\n" 
send_user ">>>>> Working on $hostname @ [exec date] <<<<<\r" 
send_user "\n" 

spawn clogin "$hostname\r" 

expect { 
    timeout { send_user "\n Failed to get login prompt\n"; exit 1 } 
    eof { send_user "\nSSH failure for hostname\n"; exit 1 } 
    "*-> $" 
    } 

sleep 2 


send "conf t\n" 
expect "#" 
send "hostname $newname\n" 
expect "#" 
send "exit\n" 
expect "(config)#" 
send "write mem\n" 
expect "*#" 
send "exit\n" 
expect ":~\$" exit 

# Announce which device we are working on and at what time 
send_user "\n" 
send_user ">>>>> Done working on $hostname @ [exec date] <<<<<\r" 
send_user "\n" 

} 

这里是我的csv文件

hostnames.csv

10.10.1.1,newhostname1 
172.16.1.2,newhostname2 
192.168.45.150,newhostname3 

我会APPR提供任何帮助。

谢谢

嗨迪内希

谢谢您的答复。

我用你提供的第一个代码,没有“句柄”部分。如果登录失败,它现在会转到下一个IP地址,但它不会在良好的登录中运行我的命令。登录到172.16.1.2是唯一的工作连接。其他人将测试故障转移。

$**expect hostnames.exp** 
10.10.1.1 
newhostname1 

>>>>> Working on 10.10.1.1 @ Wed Oct 1 11:59:09 SAST 2014 <<<<< 
spawn clogin 10.10.1.1 
10.10.1.1 

in /home/*****/.cloginrc.0.1.1 

SSH failure for hostname for 10.10.1.1 
172.16.1.2 
newhostname2 

>>>>> Working on 172.16.1.2 @ Wed Oct 1 11:59:09 SAST 2014 <<<<< 
spawn clogin 172.16.1.2 
172.16.1.2 
spawn telnet 172.16.1.2 
Trying 172.16.1.2... 
.onnected to 172.16.1.2 
Escape character is '^]'. 

User Access Verification 

Username: ***** 
Password: 
SR_Test_SW# 
SR_Test_SW# 
Failed to get login prompt for 172.16.1.2 
192.168.45.150 
newhostname3 

>>>>> Working on 192.168.45.150 @ Wed Oct 1 11:59:11 SAST 2014 <<<<< 
spawn clogin 192.168.45.150 
192.168.45.150 
spawn telnet 192.168.45.150 
Trying 192.168.45.150... 

Failed to get login prompt for 192.168.45.150 
$ 

我没有尝试你的第二个代码的“处理”部分,这也给了我错误。

如果您需要我,我会为您提供输出。

谢谢你的时间。

+0

我对第一个代码段进行了更改,并将**“* - > $”**部分替换为**“*#”{} **现在看起来好了。谢谢。 – 2014-10-03 08:18:29

+0

@ Evan van Zyl,是的,在我的答案评论部分更新错误输出。 – Dinesh 2014-10-03 14:07:23

回答

1

只需使用continue下期待timeouteof,代替exit 1

expect { 
    timeout { 
       send_user "\n Failed to get login prompt for the switch $hostname\n" 
       continue 
      } 
    eof { 
      send_user "\nSSH failure for hostname for the switch $hostname\n" 
      continue 
     } 
    "*-> $" 
} 

一个例子说明如下。

#!/usr/bin/expect 
set timeout 3 
send_user "we are waiting for the word 'hi' \n" 

#Looping for 10 times 
foreach x { 1 2 3 4 5 6 7 8 9 10} { 
     puts "Is anybody there???" 
     expect { 
       timeout { 
         puts "Nobody responding to me at trial $x" 
         puts "I'm waiting" 
         #Proceeding with the next element of the loop, using 'continue' 
         continue 
       } 
       #Dont bother about this 'nocase' keyword. ;) 
       -nocase "hi" { puts "Hey friend!" } 
     } 
} 

因为你是产卵甚至expect前“clogin”,我们是安全的在这方面,它不会引起任何问题。如果它无法到达,我们将继续产生新的'clogin'。

但是,优雅地关闭生成的过程是一种很好的做法。作为

# After this command execution, the variable 'handle' will hold 
# the spawn handle reference for the 'clogin' process 
set handle [ spawn clogin "$hostname\r" ] 

# Your expect statements here - Just modifying it for our needs 

expect { 
     timeout { 
        send_user "\n Failed to get login prompt for the switch $hostname\n" 
        # Closing the process gracefully 
        close $handle 
        continue 
       } 
     eof { 
       send_user "\nSSH failure for hostname for the switch $hostname\n" 
       close $handle 
       continue 
      } 
     "*-> $" 
} 
0

我上搜索,找到这样的剧本,但它会在三分之一的时间执行可以安排。那么,您将如何着手将列表分成三个文件/部分,然后在三个不同的会话期间执行更改。因此尽早完成。

+0

看看这个链接..:[链接](http://stackoverflow.com/questions/21508076/spawn-multiple-telnet-with-tcl-and-log-the-output-seperately) – 2014-12-10 10:41:38

相关问题