怎样用Python的telnetlib库自动化登录网络设备

访客 网络编程 1

本文目录导读:

  1. 基础环境准备
  2. 基础登录示例
  3. 完整功能实现
  4. 注意事项和最佳实践

我来详细介绍如何使用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登录的各个方面,包括基础登录、交互式处理、完整的管理类、批量操作、错误处理和安全性考虑,你可以根据具体的网络设备和需求进行调整。

标签: telnetlib 网络设备

抱歉,评论功能暂时关闭!