问题描述
我编写了一个脚本,可以通过 telnet 连接到某些网络设备并提取清单并将其放入一个文件中。我使用线程来加速脚本,因为我有大约 160 个节点。我编写了一个 telnet 到每个节点的函数,检索库存,将输出写入文件,然后断开会话。当我在单个函数下执行这三个步骤时,脚本运行良好。但是,我决定创建一个类并将这三个步骤分解为不同的方法。现在,当我运行脚本时,它只从列表中的第一个节点检索数据。我需要一些帮助来弄清楚为什么脚本不起作用。
import concurrent.futures
import time
import telnetlib
from myFunctions import get_node_list_TA5K
class Ta5kTelnet:
def __init__(self):
self.tn = telnetlib.Telnet()
def connect(self,hostname,username,password):
self.tn.open(hostname,23,5)
self.tn.read_until(b'Username:',5)
self.tn.write(username.encode('ascii') + b'\n')
self.tn.read_until(b'Password:',5)
self.tn.write(password.encode('ascii') + b'\n')
if b'>' in self.tn.read_until(b'>',5):
self.tn.write(b'en\n')
self.tn.read_until(b'#',5)
self.tn.write(b'term len 0\n')
output = self.tn.read_until(b'#',5)
return output
else:
print(f'{hostname} is spare shelf')
def send(self,command,waitfor):
self.tn.write(command + b'\n')
result = self.tn.read_until(waitfor,180).decode()
return result
def disconnect(self):
self.tn.close()
tlnt = Ta5kTelnet()
def inventory(node_names):
tlnt.connect(node_names,'username','password')
shelf_inventory = tlnt.send(b'show system inventory',b'#')
tlnt.disconnect()
with open(f'{node_names}_inventory.txt','a') as f:
f.write(shelf_inventory)
#adtran_nodes = get_node_list_TA5K()
adtran_nodes = ['BXR1-NODE1-COT1','BXR6-NODE1-COT6']
start = time.perf_counter()
with concurrent.futures.ThreadPoolExecutor() as executor:
results = executor.map(inventory,adtran_nodes)
print(time.perf_counter() - start)
解决方法
您在两个线程之间共享一个 telnet 连接,并且没有锁定或同步。
无法知道连接、登录、发送、read_until 序列将按哪个顺序运行。
每个线程都需要自己的连接对象。
此外,我会重构从 telnetlib.Telnet
派生的事物,并且在此过程中,为了确保连接始终正确关闭,请使用 __enter__
和 {{ 使其成为上下文管理器1}}:
__exit__