首页 > 解决方案 > PyCharm - OSError:套接字已关闭

问题描述

任何帮助将不胜感激!如何解决?问题似乎与 netmiko/paramiko 和它与脚本的交互有关。

提前致谢!

代码:

from netmiko import ConnectHandler

with open('Devices.txt') as f:
    file_content = f.read().splitlines()


devices = list()
for item in file_content:
    tmp = item.split(':')  #tmp is a list
    devices.append(tmp)


for device in devices:
    net_device = {
        'device_type': device[0],
        'ip': device[1],
        'username': device[2],
        'password': device[3],
        'port': 22,
        'secret': device[3],  # this is the enable password
        'verbose': True
    }

    connection = ConnectHandler(** net_device)

    if not connection.check_enable_mode():
        connection.enable()


    #connection.config_mode()
    config_file = input('Enter configuration file for device type: ' + device[0] + ' with ip ' + device[1] + ':')
    print('Sending commnands to device ...')
    with open(config_file) as config:
        commands = config.read().splitlines()
    # print(commands)

    output = connection.send_config_set(commands)
    print(output)
    print('Disconecting ....')
    print('#' * 40)


    connection.disconnect()

以上是脚本。

错误:

"C:\Users\Administrator\PycharmProjects\Python Network Automation\venv\Scripts\python.exe" "C:/Users/Administrator/PycharmProjects/Python Network Automation/Python Netmiko.py"

SSH connection established to 192.168.181.150:22
Interactive SSH session established
Enter configuration file for device type: cisco_ios with ip 192.168.181.150:Static Route Configuration.txt
Sending commnands to device …

Traceback (most recent call last):
  File "C:/Users/Administrator/PycharmProjects/Python Network Automation/Python Netmiko.py", line 37, in <module>
    output = connection.send_config_set(commands)
  File "C:\Users\Administrator\PycharmProjects\Python Network Automation\venv\lib\site-packages\netmiko\base_connection.py", line 1620, in send_config_set
    output += self.exit_config_mode()
  File "C:\Users\Administrator\PycharmProjects\Python Network Automation\venv\lib\site-packages\netmiko\cisco_base_connection.py", line 55, in exit_config_mode
    return super(CiscoBaseConnection, self).exit_config_mode(
  File "C:\Users\Administrator\PycharmProjects\Python Network Automation\venv\lib\site-packages\netmiko\base_connection.py", line 1531, in exit_config_mode
    if self.check_config_mode():
  File "C:\Users\Administrator\PycharmProjects\Python Network Automation\venv\lib\site-packages\netmiko\cisco\cisco_ios.py", line 31, in check_config_mode
    return super(CiscoIosBase, self).check_config_mode(
  File "C:\Users\Administrator\PycharmProjects\Python Network Automation\venv\lib\site-packages\netmiko\cisco_base_connection.py", line 37, in check_config_mode
    return super(CiscoBaseConnection, self).check_config_mode(
  File "C:\Users\Administrator\PycharmProjects\Python Network Automation\venv\lib\site-packages\netmiko\base_connection.py", line 1496, in check_config_mode
    self.write_channel(self.RETURN)
  File "C:\Users\Administrator\PycharmProjects\Python Network Automation\venv\lib\site-packages\netmiko\base_connection.py", line 422, in write_channel
    self._write_channel(out_data)
  File "C:\Users\Administrator\PycharmProjects\Python Network Automation\venv\lib\site-packages\netmiko\base_connection.py", line 384, in _write_channel
    self.remote_conn.sendall(write_bytes(out_data, encoding=self.encoding))
  File "C:\Users\Administrator\PycharmProjects\Python Network Automation\venv\lib\site-packages\paramiko\channel.py", line 846, in sendall
    sent = self.send(s)
  File "C:\Users\Administrator\PycharmProjects\Python Network Automation\venv\lib\site-packages\paramiko\channel.py", line 801, in send
    return self._send(s, m)
  File "C:\Users\Administrator\PycharmProjects\Python Network Automation\venv\lib\site-packages\paramiko\channel.py", line 1198, in _send
    raise socket.error("Socket is closed")
OSError: Socket is closed

Process finished with exit code 1

以上是收到的错误信息。

标签: pythonpycharm

解决方案


也许远程设备出于某种原因拒绝连接。您连续多次连接。但是,您的代码很好,但需要进行一些修改。

我知道我的答案很晚,但它可能对面临同样问题的其他人有用。

  1. 我认为从 CSV 文件中读取设备会更整洁、更容易、更方便。您不必为变量device[0]device[1]等编制索引。

CSV 文件必须完全类似于:

device_type,ip,username,password,secret
cisco_ios,192.168.1.1,cisco,cisco,
cisco_ios,192.168.1.2,cisco,cisco,

您可以在 Excel 中打开它以获得漂亮的视图。

如您所见,标题行包含 Netmiko 的相应键。

您也不需要分别为(SSH) 和(Telnet)显式设置端口22和端口。只有在网络设备上创建了旋转组和 ACL以更改默认端口时,才需要设置它。23cisco_ioscisco_ios_telnet

从 CSV 文件读取数据的唯一缺点csv.DictReader()是数据值被解析为str. "verbose": True在这种情况下不是一个选项,因为它将被解析为字符串而不是布尔值 ( 'verbose': 'True')。

您可以先使用csv.reader()而不是csv.DictReader()操作解析的数据。

  1. 从文件发送配置已经实现为Netmiko. 改为使用connection.send_config_from_file("config.txt")。它读取文件并为您完成繁重的工作。

  2. 使用上下文管理器(with statement)并删除connection.disconnect().

上述建议的完整解释:

import csv

from netmiko import ConnectHandler

# File containing network devices
with open("Devices.csv") as f:
    csvfile = csv.DictReader(f=f)
    devices = [device for device in csvfile]

# print(devices)  # <--- See output below

for device in devices:
    print(f'Connecting to {device["ip"]}')
    with ConnectHandler(**device) as conn:
        print(f'Connection established to {device["ip"]}:{device["port"]}')

        if not conn.check_enable_mode():
            conn.enable()

        # Find the device prompt.
        # The slicing here ([:-1)] is to remove the `#` sign after hostname
        hostname = conn.find_prompt()[:-1]

        # If the input file is the same for all devices, then move it up before
        # the for loop, else keep it here
        config_file = input(
            f'Enter config file for {hostname} ({device["ip"]}): '
        ).strip()

        print(f"Sending commnands to {hostname}...")
        # Using `send_config_from_file` instead of `send_config_set`
        output = conn.send_config_from_file(config_file)
        # Don't forget to save the new config if you need to
        # output += conn.save_config()  # Uncomment this line to save the new config
    print(f"Disconnected from {hostname}")
    print("#" * 40)
    print(output)
    print("#" * 40)

打印变量时devices,它看起来完全像:

[{'device_type': 'cisco_ios',
  'ip': '192.168.1.1',
  'password': 'cisco',
  'secret': '',
  'username': 'cisco'},
 {'device_type': 'cisco_ios',
  'ip': '192.168.1.2',
  'password': 'cisco',
  'secret': '',
  'username': 'cisco'}]

推荐阅读