本文目录导读:
我来详细介绍如何使用Python的telnetlib库自动化登录网络设备。
基础环境准备
import telnetlib import time # 连接参数 HOST = "192.168.1.1" # 设备IP地址 USERNAME = "admin" PASSWORD = "password" PORT = 23 # Telnet默认端口
基础登录示例
简单登录路由器/交换机
def telnet_login(host, username, password):
"""
基本Telnet登录函数
"""
try:
# 建立Telnet连接
tn = telnetlib.Telnet(host, port=23, timeout=10)
# 等待登录提示符
tn.read_until(b"Username:", timeout=5)
tn.write(username.encode('ascii') + b"\n")
# 等待密码提示符
tn.read_until(b"Password:", timeout=5)
tn.write(password.encode('ascii') + b"\n")
# 等待登录完成
time.sleep(2)
# 读取登录后的输出
output = tn.read_very_eager()
print(f"登录成功,输出:{output.decode('ascii', errors='ignore')}")
return tn
except Exception as e:
print(f"登录失败: {e}")
return None
# 使用示例
tn = telnet_login(HOST, USERNAME, PASSWORD)
交互式登录(处理不同提示符)
def interactive_telnet_login(host, username, password):
"""
处理不同的登录提示符
"""
try:
tn = telnetlib.Telnet(host, 23, 10)
# 读取并处理登录提示
login_prompt = tn.expect([
b"Username:", # 常见的用户名提示
b"login:", # Unix/Linux风格的提示
b"username:", # 小写版本
b">", # 某些设备的提示
], timeout=5)
if login_prompt[0] in [0, 1, 2]: # 找到了用户名提示
tn.write(username.encode('ascii') + b"\n")
elif login_prompt[0] == 3: # 直接进入enable模式
tn.write(b"enable\n")
tn.read_until(b"Password:", timeout=5)
tn.write(password.encode('ascii') + b"\n")
return tn
# 等待密码提示
password_prompt = tn.expect([
b"Password:", # 常见的密码提示
b"password:", # 小写版本
], timeout=5)
tn.write(password.encode('ascii') + b"\n")
# 等待登录成功
time.sleep(2)
return tn
except Exception as e:
print(f"交互式登录失败: {e}")
return None
完整功能实现
完整的网络设备管理类
class NetworkDeviceManager:
"""
网络设备管理器 - 支持Telnet登录和命令执行
"""
def __init__(self, host, username, password, port=23, timeout=10):
self.host = host
self.username = username
self.password = password
self.port = port
self.timeout = timeout
self.tn = None
self.is_connected = False
def connect(self):
"""
建立Telnet连接并登录
"""
try:
print(f"正在连接到 {self.host}:{self.port}...")
self.tn = telnetlib.Telnet(self.host, self.port, self.timeout)
# 等待并处理登录提示
login_data = self.tn.read_until(b"Username:", timeout=self.timeout)
self.tn.write(self.username.encode('ascii') + b"\n")
# 等待密码提示
password_data = self.tn.read_until(b"Password:", timeout=self.timeout)
self.tn.write(self.password.encode('ascii') + b"\n")
# 等待登录完成
time.sleep(2)
# 读取初始输出
output = self.tn.read_very_eager()
print(f"登录成功!")
self.is_connected = True
return True
except Exception as e:
print(f"连接失败: {e}")
return False
def send_command(self, command, wait_time=2):
"""
发送命令并获取返回结果
Args:
command: 要执行的命令
wait_time: 等待响应的时间(秒)
Returns:
命令执行结果的字符串
"""
if not self.is_connected or not self.tn:
print("未建立连接")
return None
try:
# 发送命令
self.tn.write(command.encode('ascii') + b"\n")
time.sleep(wait_time)
# 读取输出
output = self.tn.read_very_eager().decode('ascii', errors='ignore')
return output
except Exception as e:
print(f"命令执行失败: {e}")
return None
def enter_enable_mode(self, enable_password):
"""
进入特权模式(适用于Cisco设备)
"""
try:
self.tn.write(b"enable\n")
time.sleep(1)
# 读取输出
output = self.tn.read_very_eager().decode('ascii', errors='ignore')
print(f"Enable提示: {output}")
# 检查是否需要密码
if "Password" in output or "password" in output:
self.tn.write(enable_password.encode('ascii') + b"\n")
time.sleep(1)
# 读取输出
output = self.tn.read_very_eager().decode('ascii', errors='ignore')
print(f"进入特权模式: {output}")
return True
except Exception as e:
print(f"进入特权模式失败: {e}")
return False
def configure_terminal(self):
"""
进入配置模式(适用于Cisco设备)
"""
return self.send_command("configure terminal")
def show_running_config(self):
"""
查看运行配置
"""
return self.send_command("show running-config", wait_time=3)
def show_interfaces(self):
"""
查看接口状态
"""
return self.send_command("show ip interface brief", wait_time=2)
def save_configuration(self):
"""
保存配置(Cisco设备)
"""
# 退出配置模式
self.send_command("end")
# 保存配置
result = self.send_command("write memory", wait_time=3)
return result
def disconnect(self):
"""
断开连接
"""
if self.tn:
try:
# 退出并关闭连接
self.tn.write(b"exit\n")
self.tn.close()
print("连接已关闭")
except:
pass
self.is_connected = False
self.tn = None
def __enter__(self):
"""上下文管理器入口"""
self.connect()
return self
def __exit__(self, exc_type, exc_val, exc_tb):
"""上下文管理器出口"""
self.disconnect()
# 使用示例
if __name__ == "__main__":
# 使用上下文管理器自动管理连接
with NetworkDeviceManager(
host="192.168.1.1",
username="admin",
password="password"
) as device:
if device.is_connected:
# 查看设备信息
print("=== 查看设备信息 ===")
result = device.send_command("show version")
print(result)
# 查看接口状态
print("=== 查看接口状态 ===")
result = device.show_interfaces()
print(result)
# 保存配置
print("=== 保存配置 ===")
result = device.save_configuration()
print(result)
批量设备管理
def batch_manage_devices(device_list, commands):
"""
批量管理多个设备
"""
results = {}
for device_info in device_list:
host = device_info['host']
username = device_info.get('username', 'admin')
password = device_info.get('password', 'password')
print(f"\n{'='*50}")
print(f"处理设备: {host}")
print('='*50)
try:
with NetworkDeviceManager(host, username, password) as device:
if device.is_connected:
device_results = {}
for cmd in commands:
print(f"执行命令: {cmd}")
result = device.send_command(cmd)
device_results[cmd] = result
results[host] = device_results
except Exception as e:
print(f"设备 {host} 处理失败: {e}")
results[host] = f"Error: {e}"
return results
# 批量处理示例
devices = [
{"host": "192.168.1.1", "username": "admin", "password": "pass1"},
{"host": "192.168.1.2", "username": "admin", "password": "pass2"},
{"host": "10.0.0.1", "username": "root", "password": "pass3"},
]
commands = [
"show system info",
"show interfaces",
"show running-config"
]
results = batch_manage_devices(devices, commands)
注意事项和最佳实践
错误处理增强
def robust_telnet_session(host, username, password, max_retries=3):
"""
带重试机制的Telnet会话
"""
for attempt in range(max_retries):
try:
tn = telnetlib.Telnet(host, 23, timeout=10)
# 登录逻辑
tn.read_until(b"Username:", timeout=5)
tn.write(username.encode('ascii') + b"\n")
tn.read_until(b"Password:", timeout=5)
tn.write(password.encode('ascii') + b"\n")
# 验证登录成功
time.sleep(2)
output = tn.read_very_eager()
if b"Login invalid" in output or b"Authentication failed" in output:
print(f"认证失败 (尝试 {attempt + 1}/{max_retries})")
tn.close()
continue
print("登录成功")
return tn
except Exception as e:
print(f"连接失败 (尝试 {attempt + 1}/{max_retries}): {e}")
if attempt < max_retries - 1:
time.sleep(2) # 等待后重试
return None
安全考虑
from getpass import getpass
def secure_telnet_login(host):
"""
安全的Telnet登录(不硬编码密码)
"""
username = input("请输入用户名: ")
password = getpass("请输入密码: ") # 隐藏密码输入
tn = telnetlib.Telnet(host, 23, 10)
tn.read_until(b"Username:", timeout=5)
tn.write(username.encode('ascii') + b"\n")
tn.read_until(b"Password:", timeout=5)
tn.write(password.encode('ascii') + b"\n")
time.sleep(2)
return tn
日志记录
import logging
from datetime import datetime
# 配置日志
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s',
handlers=[
logging.FileHandler('telnet_operations.log'),
logging.StreamHandler()
]
)
class TelnetSessionWithLogging(NetworkDeviceManager):
"""
带日志的Telnet会话
"""
def send_command(self, command, wait_time=2):
logging.info(f"发送命令到 {self.host}: {command}")
result = super().send_command(command, wait_time)
if result:
logging.info(f"命令执行成功,输出长度: {len(result)} 字符")
# 记录部分输出到日志
logging.debug(f"命令输出前200字符: {result[:200]}")
else:
logging.error(f"命令执行失败: {command}")
return result
def log_error(self, message):
"""记录错误信息"""
logging.error(f"{self.host}: {message}")
with open('error_log.txt', 'a') as f:
f.write(f"{datetime.now()} - {self.host}: {message}\n")
这个完整的示例涵盖了Telnet登录的各个方面,包括基础登录、交互式处理、完整的管理类、批量操作、错误处理和安全性考虑,你可以根据具体的网络设备和需求进行调整。