我正在努力构建一个包含多线程的脚本。
[我的目标:][1] [1]:https://i.stack.imgur.com/P4yuy.png
该脚本的目标是使用线程连接到多个设备并使用顺序方法执行命令,这样我就可以有一个干净的输出,这样输出就可以有序了。
# ~~~~~~~~
# Import modules
# ~~~~~~~~
import subprocess, logging, re, getpass
from netmiko import ConnectHandler
from netmiko.ssh_exception import NetMikoTimeoutException, NetMikoAuthenticationException
from paramiko.ssh_exception import SSHException
import threading, time
from queue import Queue
logging.basicConfig(level=logging.INFO,
format="{asctime} {levelname:<8} {message}",
style='{',
filename='%slog' % __file__[:-2],
filemode='a'
)
##logging.info("this is a message")
# ~~~~~~~~
# Define functions
# ~~~~~~~~
dev_list = []
success_dev = []
failed_dev = []
def ping_ip(ip):
global gips
rstlongstr = ''
(output,error) = subprocess.Popen((['ping', ip, '-c', '2']), stdin=subprocess.PIPE, stdout=subprocess.PIPE, universal_newlines=True).communicate()
if 'bytes from' in output:
dev_list.append(ip)
logging.info(output)
print (output)
reg_rttavg = re.findall(r'(?=rtt.*=\s[\d.]+\/([\d.]+))',output)
strpreg_rttavg = [test2.strip() for test2 in reg_rttavg]
str_rttavg = '\n'.join(strpreg_rttavg)
reg_ploss = re.findall(r'[\d%.]+(?= packet loss)',output)
strpreg_ploss = [test2.strip() for test2 in reg_ploss]
str_ploss = '\n'.join(strpreg_ploss)
#return ".....Device is Reachable - " + ip
return "[ " + ip + " ] Reachable - rtt(avg): %s ploss: %s" % (str_rttavg,str_ploss)
elif 'Host Unreachable' in output:
print (output)
return "[ " + ip + " ] Unreachable"
else:
#return "Unreachable"
print (output)
return "[ " + ip + " ] Unreachable"
thread_q.put
def connect_now(ip_a,username,password,enable_s):
global success_dev, failed_dev,output_dict
output_dict = {}
print ('[ ' + ip_a + ' ] Loging into IP')
try:
device_conn = ConnectHandler(device_type='cisco_ios_ssh', ip=ip_a,
username=username, password=password,
secret=enable_s, verbose=True)
output_q.put(output_dict)
device_conn.enable()
hostname = device_conn.find_prompt()
print ("hostname:", hostname)
with open('out.txt', 'a') as DATAFILE:
print(hostname, file=DATAFILE)
sh_commands = ['show run | i hostname', 'show clock']
for cmd in sh_commands:
print ("Sending command: ",cmd)
time.sleep(2)
result_out = device_conn.send_command(cmd)
output_dict = {}
output_dict[hostname].append(result_out)
print ("## ## ## dict: ",output_dict)
#output_dict[hostname].append(result_out)
## print(result_out, file=DATAFILE)
device_conn.disconnect()
print ('[ ' + ip_a + ' ] Logged out')
success_dev.append(hostname)
except:
print ('[ ' + ip_a + ' ] Unable to access')
failed_dev.append(ip_a)
## output_q.put
#~~~~~~~~~~~~~~
#MAIN
#~~~~~~~~~~~~~~
ipadd = ['192.168.2.111',"192.168.2.113", '9.9.9.222','192.168.2.112',"192.168.2.66",]
thread_q = Queue()
for x in ipadd:
print ("Pinging: ",x)
m_thread = threading.Thread(target=ping_ip, args=(x,))
m_thread.start()
m_thread.join()
print (dev_list)
uname = "test"
pswd = "test"
ena = "test"
if uname == "" or pswd == "" or ena == "":
print('username, password or enable_secret cannot be empty. Please enter valid credentials!!!')
logging.info("username, password or enable_secret cannot be empty. Please enter valid credentials!!!")
sys.exit()
logging.info("List of reachable device: " + str(dev_list))
NUM_THREADS = 3 # TARGET NUMBER OF DEVICES
num_threads = min(NUM_THREADS, len(dev_list))
start = time.time()
output_q = Queue()
for ip in dev_list:
print ("Processing: ",ip)
worker = threading.Thread(target=connect_now, args=(ip,uname,pswd,ena))
worker.start()
worker.join()
print (output_dict)
end = time.time()
total = int(end - start)
print("\n Elapsd Time: " + str(total) + " Sec\n")
除此之外是将输出放入字典 output_dict 中,因此我使用此代码 output_dict[hostname].append(result_out) 将值放入列表格式但不起作用。
问题:
- 如何修复或正确使用线程,我可以看到一些输出,但由于线程的原因,大部分都看不到。
- 如何将输出添加为字典值但作为列表。ex {'CSRV#': ['outputa','outputb']}
先感谢您。希望您能够帮助我。