您好,登錄后才能下訂單哦!
新浪微博: @wandering
博客地址: dayong.info
在深入進(jìn)行網(wǎng)絡(luò)工作一段時(shí)間后,開(kāi)始著手解決AAA、NTP、SYSLOG基礎(chǔ)服務(wù)(簡(jiǎn)稱:基礎(chǔ)服務(wù))的可用性和線上設(shè)備相關(guān)配置的正確性問(wèn)題。
前期,一邊優(yōu)化、重構(gòu)基礎(chǔ)服務(wù),一邊修正線上配置。但這個(gè)項(xiàng)目是個(gè)系統(tǒng)工程,無(wú)法在短期內(nèi)完成,因此即要保持戰(zhàn)果讓已修正的配置不再出錯(cuò),還希望新增加的設(shè)備可以直接進(jìn)行正確配置。另外,如何保證其他工程師也正確配置設(shè)備,也是需要解決的問(wèn)題,畢竟工作最終是需要多個(gè)團(tuán)隊(duì)共同協(xié)作的。
因此,自動(dòng)檢查線上所有重要交換機(jī)和路由器的網(wǎng)管服務(wù)、Spanning-Tree、VTP Mode等重要配置是否正確,成了必須優(yōu)先解決的問(wèn)題。
最直接的方法就是直接檢查相應(yīng)配置,這符合網(wǎng)絡(luò)管理人員的思維和操作習(xí)慣。因此,決定優(yōu)先解決多臺(tái)設(shè)備的批量執(zhí)行命令需求。
本人一直對(duì)程序設(shè)計(jì)有這樣的觀點(diǎn),不能解決問(wèn)題的程序不是好程序,因此程序首先要實(shí)現(xiàn)功能,其次才是程序的效能。只有在規(guī)模、需求達(dá)到相當(dāng)程度后才有必要對(duì)效率、性能追求極致。對(duì)非專業(yè)開(kāi)發(fā)人員來(lái)說(shuō)更是要注意精力、時(shí)間的分配,20%的投入獲得80%的回報(bào)其投入產(chǎn)出比是相當(dāng)可觀的,再多花80%的精力去提升最多20%的性能是必須慎重對(duì)待的。因此,決定采用模擬人機(jī)交互方式實(shí)現(xiàn)網(wǎng)絡(luò)設(shè)備的批量化操作。
程序?qū)崿F(xiàn)基本邏輯是:
1)自動(dòng)登錄交換機(jī)、路由器批量執(zhí)行命令,將結(jié)果輸出。
2)對(duì)輸出結(jié)果進(jìn)行二次處理,實(shí)現(xiàn)不同目標(biāo)。
這樣,基本可以解決大部分網(wǎng)絡(luò)管理需要,其主要優(yōu)點(diǎn)是簡(jiǎn)單,會(huì)操作交換機(jī)/路由器的人就可以使用。但是,此方法最大的問(wèn)題是效率,因?yàn)楸举|(zhì)上只是由程序模仿手工操作,需要考慮cli可以接受的操作頻率等問(wèn)題。曾考慮過(guò)SNMP、TCL-Script、NET-CONF等方法,但考慮到自己的能力及精力分配、跨廠商平臺(tái)兼容性問(wèn)題最終放棄。
網(wǎng)上可以查到的模擬人工命令交互操作的方法有2個(gè):perl、expect
首先考慮的是perl,因?yàn)橛衟erl編程基礎(chǔ),有其他同事寫(xiě)好的相似功能腳本,但最終放棄。因?yàn)閜erl的switch模塊不支持Cisco的Nexus平臺(tái)內(nèi)容輸出,其解決方法非常復(fù)雜,要修改switch模塊的源代碼,這樣會(huì)產(chǎn)生自己的分支,管理維護(hù)成本太高,不利于程序的持續(xù)開(kāi)發(fā)和推廣 。
最后,選擇expect,其原理是執(zhí)行命令,根據(jù)不同輸出反饋采取不同操作,重復(fù)這個(gè)過(guò)程。
關(guān)于expect的學(xué)習(xí)使用,不在本文的關(guān)注范圍。
以下最新版本的代碼:
#!/usr/local/bin/expect # # Statement: sw-telnet.exp <ip> <cmd-prefix> <uid> <pwd> # # <ip> ip for telnet # <cmd-prefix> For example, sw-backup is cmd-prefix of sw-backup.cmd.h4c and # sw-backup.cmd.cisco # <uid> uid for telnet # <pwd> pwd for telnet # # # Depends: <cmd-prefix>.cmd.h4c # <cmd-prefix>.cmd.cisco # # # Last modified: 2012/05/24 # # set path_cmd "/aaa/bin" set cmd_telnet "telnet" set timeout_default 10 set timeout $timeout_default set vendor "cisco" # Arg 1 set ip [lindex $argv 0] if { $ip == "" } { puts "" puts "Statement: command <ip> <cmd-prefix> <uid> <pwd>" puts " ^^" puts " <ip> ip for telnet" puts " <cmd-prefix> For example, sw-backup is cmd-prefix of sw-backup.cmd.h4c and" puts " sw-backup.cmd.cisco" puts " <uid> uid for telnet" puts " <pwd> pwd for telnet" puts "" exit 1 } # Arg 2 set cmd_prefix [lindex $argv 1] if { $cmd_prefix == "" } { puts "" puts "Statement: command <ip> <cmd-prefix> <uid> <pwd>" puts " ^^^^^^^^^^" puts " <ip> ip for telnet" puts " <cmd-prefix> For example, sw-backup is cmd-prefix of sw-backup.cmd.h4c and" puts " sw-backup.cmd.cisco" puts " <uid> uid for telnet" puts " <pwd> pwd for telnet" puts "" exit 1 } # Arg 3 set uid [lindex $argv 2] if { $uid == "" } { #set uid "backup" puts "" puts "Statement: command <ip> <cmd-prefix> <uid> <pwd>" puts " ^^^" puts " <ip> ip for telnet" puts " <cmd-prefix> For example, sw-backup is cmd-prefix of sw-backup.cmd.h4c and" puts " sw-backup.cmd.cisco" puts " <uid> uid for telnet" puts " <pwd> pwd for telnet" puts "" exit 1 } # Arg 4 set pwd [lindex $argv 3] if { $pwd == "" } { #set pwd "M2dpSF6rSU" puts "" puts "Statement: command <ip> <cmd-prefix> <uid> <pwd>" puts " ^^^" puts " <ip> ip for telnet" puts " <cmd-prefix> For example, sw-backup is cmd-prefix of sw-backup.cmd.h4c and" puts " sw-backup.cmd.cisco" puts " <uid> uid for telnet" puts " <pwd> pwd for telnet" puts "" exit 1 } #___ start telnet ___ spawn $cmd_telnet "$ip" sleep 1 expect "H3C" { set vendor "h4c" } expect -re "Username:|Login:|login:" { send "$uid\r" sleep 1 } expect "Password:" { send "$pwd\r" sleep 1 } #_____ login failed _____ expect { "Access denied" { exit } "Connection refused" { exit } "Login failed" { exit } "Login incorrect" { exit } "Login invalid" { exit } "Password incorrect." { exit } "timeout expired!" { exit } } #_____ Command sets selection by vendor (cisco, h4c) _____ switch -- $vendor cisco { # vendor: cisco set timeout_cisco 60 set timeout $timeout_cisco #___ get commands __ set file [ open "$path_cmd/$cmd_prefix.cmd.$vendor" "r" ] set cmd_count 0 while 1 { if { [gets $file line] == -1 } break incr cmd_count set cmd_list($cmd_count) $line } close $file expect -re ".*# *$" send "term len 0\r\n\n\n" set i 1 while { $i <= $cmd_count } { expect -re ".*# *$" send "$cmd_list($i)\r\n\n\n" incr i sleep 1 } expect -re ".*# *$" send "exit\r" } h4c { # vendor: h4c set timeout_h4c 10 set timeout $timeout_h4c #___ get commands __ set file [ open "$path_cmd/$cmd_prefix.cmd.$vendor" "r" ] set cmd_count 0 while 1 { if { [gets $file line] == -1 } break incr cmd_count set cmd_list($cmd_count) $line } close $file set i 1 while { $i <= $cmd_count } { expect -re "<.*>$" send "$cmd_list($i)\r\r\r\r" expect -re "\- More \-+$" { set timeout 3 set more "yes" while {$more == "yes"} { #puts "___ more ___\r" send " " expect -re "<.*>$" { #puts "___ there's no more ___" set more "no" } } set timeout $timeout_h4c } incr i sleep 1 } expect -re "<.*>$" send "quit\r" } default { # vendor: unkown puts "\nError: Unkown Vendor!\n" exit } expect eof puts "\nVendor: $vendor" puts "Command list:" set i 1 while { $i <= $cmd_count } { puts "$i) $cmd_list($i)" incr i } puts "" exit
*注:腳本目前只支持Cisco和H3C兩個(gè)主流平臺(tái)。
*注:注意設(shè)置程序運(yùn)行路徑變量 path_cmd 。
舉例,假設(shè)需要對(duì)設(shè)備1.2.3.4做以下操作:
1)備份running-config
2)查看cpu狀態(tài)
首先,需要建立4個(gè)文件,腳本會(huì)自動(dòng)判斷Cisco或H3C設(shè)備類型執(zhí)行相應(yīng)命令集:
1)backup.cmd.cisco
dir show ver show inv show run
2)backup.cmd.h4c
dir disp verion disp device manuinfo disp curr
3)version.cmd.cisco
show process cpu sort | exclude 0.00% show process cpu history
4)version.cmd.h4c
display cpu-usage
其次,寫(xiě)crontab:
0 3 * * * /aaa/bin/sw-telnet.exp 1.2.3.4 backup test_uid test_pwd > /bak/1.2.3.4_show-run_$(date +"%Y%m%d")
*/10 * * * * /aaa/bin/sw-telnet.exp 1.2.3.4 version test_uid test_pwd >> /bak/1.2.3.4_show-ver_$(date +"%Y%m%d")
OK,這樣就實(shí)現(xiàn)了對(duì)1.2.3.4的自動(dòng)抓取running-config和記錄cpu狀態(tài)。
在此代碼基礎(chǔ)上,完成了以下工作:
對(duì)全網(wǎng)重要設(shè)備抓取running-config,并實(shí)現(xiàn)關(guān)鍵配置檢查報(bào)警
對(duì)某產(chǎn)品相關(guān)服務(wù)器接入交換機(jī)端口進(jìn)行流量監(jiān)控、報(bào)警(公司監(jiān)控不能查看port-channel屬性)
對(duì)某IDC核心交換機(jī)的mac地址表監(jiān)控,增減幅度超過(guò)5%報(bào)警
自動(dòng)批量執(zhí)行命令腳本是核心代碼,可以通過(guò)其它程序調(diào)用實(shí)現(xiàn)更復(fù)雜的功能,例如對(duì)多個(gè)IP批量操作,具體實(shí)現(xiàn)本文不再贅述。
希望本文能夠?qū)τ行枰呐笥延兴鶐椭?,程序代碼可以任意使用。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。