telnetlib/SNMP
telnetlib
- telnetlib
总体来讲还是很好理解的,因为已经耍过paramiko
关于 .read_very_eager(), 简单理解就是就是读尽量多,读到没有反馈了为止
- 关键功能
1) 从telnetlib引用过来的第一个要被用到的:
telnetlib.Telnet(ip_addr, TELNET_PORT, TELNET_TIMEOUT)
这个货的作用就是return一个connection给你
2) remote_conn.read_util(“some_string”, TELNET_TIMEOUT)
下面在用这个功能的时候,用了一点小花招就是,因为返回的Username提示语的首字母不知道是不是大写的U,password的P也不知道是不是大写的P,所以只匹配其中的一部分,不知道这个地方用regex能不能行
3) remote_conn.write(“some_string”)
➜ hsun_pynet_dry_run git:(master) cat test_telnet.py
import telnetlib
import time
TELNET_PORT = 23
TELNET_TIMEOUT = 6
def main():
ip_addr = '128.223.51.103'
username = 'rviews'
password = ''
remote_conn = telnetlib.Telnet(ip_addr, TELNET_PORT, TELNET_TIMEOUT)
output = remote_conn.read_until("sername:", TELNET_TIMEOUT)
remote_conn.write(username + '\n')
time.sleep(2)
output = remote_conn.read_very_eager()
print output
remote_conn.write("show version"+ '\n')
time.sleep(4) # 注意这个地方的4秒,因为我连接的是很远端的一个public router,速度不是很好
output = remote_conn.read_very_eager()
print output
if __name__ == "__main__":
main()
- 针对思科设备的 —more— 翻页
遇到这种需要翻页的情况,在show version前面那一行添加
remote_conn.write("terminal len 0" + '\n')
time.sleep(2)
似乎没有其他的更好的办法
- 提高可复用性 reusability
可以看到在上述的代码中,有很多重复的remote_conn 和 print output等,依据是他们可能有功能的variable,调用共同的BIF 如print,这就提醒我们应该注意代码复用,减少不必要的复制粘贴
当然,在复制粘贴时,用yy命令在vim里会很省力,4yy就是copy4行,但是vim和clipboard的兼容性经常存在问题,需要调整 ~/.vimrc
➜ hsun_pynet_dry_run git:(master) cat telnetlib_reuse.py
import telnetlib
import time
TELNET_PORT = 23
TELNET_TIMEOUT = 6
def send_command(remote_conn, cmd):
cmd = cmd.rstrip()
remote_conn.write(cmd + '\n')
time.sleep(4)
return remote_conn.read_very_eager()
def login(remote_conn, username, password=''):
output = remote_conn.read_until("sername:", TELNET_TIMEOUT)
remote_conn.write(username + '\n')
if len(password) > 1:
output = remote_conn.read_util("ssword:", TELNET_TIMEOUT)
remote_conn.write(password + '\n')
else:
return output
def main():
ip_addr = '128.223.51.103'
username = 'rviews'
password = ''
remote_conn = telnetlib.Telnet(ip_addr, TELNET_PORT, TELNET_TIMEOUT)
login(remote_conn, username, password)
time.sleep(2)
output = remote_conn.read_very_eager()
print output
output = send_command(remote_conn, 'terminal len 0')
output = send_command(remote_conn, 'show version')
print output
remote_conn.close()
if __name__ == "__main__":
main()
- 异常处理 socket.timeout
比如我把IP改成一个不能telnet的了,就会触发
socket.timeout: timed out
为了避免这一现象,因为这一现象会阻断程序的运行,如果你处理的是一连串的connection,因为一个connection断了后面的执行,你肯定不希望看到这样,所以下面在remote_conn的前后加上了异常处理
try:
return telnetlib.Telnet(ip_addr, port, timeout)
except socket.timeout:
sys.exit("Connection timed-out")# 为了使用sys.exit,需要import sys
- 进一步的提高reusability
把刚刚的异常处理和telnetlib.Telnet这个核心功能提取出来,方便以后如果同时处理几十个连接
def create_a_conn(ip_addr, port, timeout):
try:
return telnetlib.Telnet(ip_addr, port, timeout)
except socket.timeout:
sys.exit("Connection timed-out")
<skip def send_command and def login>
def main():
ip_addr = '128.223.51.103'
username = 'rviews'
password = ''
remote_conn = create_a_conn(ip_addr, TELNET_PORT, TELNET_TIMEOUT)
login(remote_conn, username, password)
time.sleep(2)
output = remote_conn.read_very_eager()
print output
output = send_command(remote_conn, 'terminal len 0')
output = send_command(remote_conn, 'show version')
print output
remote_conn.close()
改完之后总的代码在这里
https://github.com/zoomhgtk/hsun_pynet_dry_run/blob/master/class2/telnetlib_reuse.py
SNMP
- SNMP的OID
这是我们最常用到的,其他的概念可以去看TCP/IP 卷一的第25章。OID即object identifier, 卷一的25.4对它有详细的讲解。我们用OID就是为了从网络设备里,通过SNMP(而不是SSH/Telnet)提取我们想要的特定的信息。
- Cisco OID工具
想要获取到准确的OID值,就到这个链接 http://snmp.cloudapps.cisco.com/Support/SNMP/do/BrowseOID.do
- snmpget
这是个Linux上很常用的命令, 下面这个命令最右端的OID就是从上面思科的那个链接那里copy的,但是要注意的是思科网站上给出来的是‘1.3.6.1.2.1.1.1’,但是不能直接用,因为长度不够,需要末尾补充一个‘0’
➜ ~ snmpget -v 2c -c public 172.25.0.37 1.3.6.1.2.1.1.1.0
SNMPv2-MIB::sysDescr.0 = STRING: Cisco IOS Software, 2800 Software (C2800NM-ADVIPSERVICESK9-M), Version 12.4(24)T4, RELEASE SOFTWARE (fc2)
Technical Support: http://www.cisco.com/techsupport
Copyright (c) 1986-2010 by Cisco Systems, Inc.
Compiled Fri 03-Sep-10 05:39 by prod_rel_team
➜ ~
- snmpwalk
遍历SNMP某个枝干上的所有
- snmp_helper
1) 这是Kirk写的一个module(locate 命令会找到一个 snmp_helper.py而不是package)
2) 用法,下面是最常用的一套套路
a_device 是一个tuple,中文好像叫元组,注意他的内容的存放顺序,一共三个元素,第一个是ip,第二个是community值,第三个是端口号
snmp_helper.snmp_get_oid(a_device, OID), 这个我感觉叫get_by_oid更合适,因为就是通过OID取出想要的值,而不是取OID, 取出来的值是比较杂乱的,就是snmpget直接出来的结果,不好看,所以用snmp_extract提取一下有用的信息,剔除那些没用的信息,output = snmp_helper.snmp_extract(snmp_data),最后print output
➜ ~ python
Python 2.7.5 (default, Mar 9 2014, 22:15:05)
[GCC 4.2.1 Compatible Apple LLVM 5.0 (clang-500.0.68)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import snmp_helper
>>> OID = '1.3.6.1.2.1.1.1.0'
>>> ip_addr = '172.25.0.37'
>>> commu = 'public'
>>> port = 161
>>>
>>> a_device = (ip_addr, commu, port)
>>>
>>> snmp_data = snmp_helper.snmp_get_oid(a_device, OID)
>>>
>>> output = snmp_helper.snmp_extract(snmp_data)
>>>
>>> print output
Cisco IOS Software, 2800 Software (C2800NM-ADVIPSERVICESK9-M), Version 12.4(24)T4, RELEASE SOFTWARE (fc2)
Technical Support: http://www.cisco.com/techsupport
Copyright (c) 1986-2010 by Cisco Systems, Inc.
Compiled Fri 03-Sep-10 05:39 by prod_rel_team
>>>
使用到的vim相关技巧
- 复制相关的
yy
4yy
yy(yank)和:t的差别详见“Vim实用技巧”P132 第十章 复制与粘贴
- ~/.vimrc相关
直接在命令行的任意处
vim ~/.vimrc
最后我的vimrc如下,添加了几个功能
前两行是添加Python的关键词高亮和自动缩进的
后两行是一直让行号显示,并且设置行号区域的数字的颜色和行号区域的背景颜色的(注意是行号的区域)
syntax on
filetype indent plugin on
set number
highlight LineNr ctermfg=black ctermbg=LightCyan
- 候选词补全
ctl + N 和 P
- 取消使用 ? / 搜索后的常高亮
:noh
- 缩进一个code block
Use the > command. To indent 5 lines, 5>>. To mark a block of lines and indent it, Vjj> to indent 3 lines (vim only). To indent a curly-braces block, put your cursor on one of the curly braces and use >%.
overall view
- 既然可以通过telnet得出一些show 命令的output了,那么就可以联系上周的parse,因为很多的output都是Cisco IOS 风格的,有着同样规律的缩进,然后就可以把output装进list里,进一步可以针对list特定的item在做进一步的show等