问题描述
我正在编写一个脚本来连接到一堆 cisco 路由器并在它们上运行命令,主机和命令被放入一个文本文件中,然后从脚本中读取.下面是我得到的代码,当我不使用 pool.map 时一切正常,但是当尝试使用 pool.map 生成更多进程时,我不断收到错误.
I am writing a script to connect to a bunch of cisco routers and run commands on them, hosts and commands are put into a text file and then read from the script. Below is the code i got, when i don't use the pool.map everything works good, but when trying to use the pool.map to spawn more process, i keep getting errors.
#!/usr/bin/python
#Import modules
from multiprocessing.pool import ThreadPool
import sys, os
import paramiko
import time
import getpass
import socket
def unpack_call(callable_arguments):
callable, arguments = callable_arguments
return callable(*arguments)
def conn(host, commands):
# Create instance of SSH client object
remote_conn_pre = paramiko.SSHClient()
# Automatically add untrusted hosts
remote_conn_pre.set_missing_host_key_policy(paramiko.AutoAddPolicy())
try:
# Pass host to connect to device via SSH
remote_conn_pre.connect(host, username=username, password=password, look_for_keys=False, allow_agent=False, timeout=5)
print "Working on %s" % host
remote_conn = remote_conn_pre.invoke_shell()
output = remote_conn.recv(1000)
disable_paging(remote_conn)
remote_conn.send("enable")
remote_conn.send("\n")
remote_conn.send(password)
remote_conn.send("\n")
output = command(commands, remote_conn,host)
remote_conn.close()
print "Completed %s" % host
except (paramiko.SSHException, socket.error) as se:
print "Error connecting to %s and reason is %s" % (host, se)
time.sleep(1)
def disable_paging(remote_conn):
''' Disable Paging on Cisco '''
remote_conn.send("term len 0\n")
time.sleep(1)
# Clear the buffer on the screen
output = remote_conn.recv(1000)
return output
def command(commands,remote_conn,host):
# Open commands.txt file for reading
c = open(commands, "r")
fil = open("session_%s.txt" % host, "w")
for l in c:
remote_conn.send(l)
time.sleep(1)
output = remote_conn.recv(50000)
fil.write(output)
fil.close()
if __name__ == "__main__":
# Get login credentials before starting script
username = raw_input("Username: ")
password = getpass.getpass("Password: ")
host = sys.argv[1]
commands = sys.argv[2]
hostnames = []
h = open("hosts.txt", "r")
for hos in h:
# conn(hos.strip(),commands)
hostnames.append(hos.strip())
h.close()
pool = ThreadPool(5)
pool.map(unpack_call, [(conn, (hostname,commands)) for hostname in hostnames])
pool.close()
pool.join()
更新:更新代码后,我现在收到此错误
UPDATE: After updating code i am now getting this error
Traceback (most recent call last):
File "getinfoTH.py", line 91, in <module>
pool.map(unpack_call, [(conn, (hostnames,commands)) for hostname in hostnames])
File "/usr/lib64/python2.7/multiprocessing/pool.py", line 250, in map
return self.map_async(func, iterable, chunksize).get()
File "/usr/lib64/python2.7/multiprocessing/pool.py", line 554, in get
raise self._value
TypeError: getaddrinfo() argument 1 must be string or None
更新:使用 map 而不是 pool.map,下面是堆栈跟踪
UPDATE: used map instead of pool.map and below is the stack trace
Traceback (most recent call last):
File "getinfo.py", line 93, in <module>
map(unpack_call, [(conn, (hostnames,commands)) for hostname in hostnames])
File "getinfo.py", line 15, in unpack_call
return callable(*arguments)
File "getinfo.py", line 32, in conn
remote_conn_pre.connect(host, username=username, password=password, look_for_keys=False, allow_agent=False, timeout=5)
File "/usr/lib/python2.7/site-packages/paramiko/client.py", line 296, in connect
to_try = list(self._families_and_addresses(hostname, port))
File "/usr/lib/python2.7/site-packages/paramiko/client.py", line 200, in _families_and_addresses
addrinfos = socket.getaddrinfo(hostname, port, socket.AF_UNSPEC, socket.SOCK_STREAM)
TypeError: getaddrinfo() argument 1 must be string or None
推荐答案
您正在将 commands
(一个 str
)作为 chunksize
(一个int
).
You are passing commands
(a str
) as chunksize
(an int
).
# your code
pool.map(conn,hostnames,commands)
# multiprocessing documentation
pool.map(func, iterable, chunksize)
请注意,与 map
不同, Pool.map
只接受 一个 可迭代的.您必须将函数更改为仅接受一个参数,或者添加一个包装器来解包参数:
Note that unlike map
, Pool.map
takes only one iterable. You must either change your function to take only one argument, or add a wrapper to unpack arguments:
def unpack_call(callable_arguments):
callable, arguments = callable_arguments
return callable(*arguments)
...
pool.map(unpack_call, [(conn, (hostname,commands)) for hostname in hostnames])
# ^ ^ ^ arguments
# | | command
# | unpack helper
这篇关于python多处理paramiko ssh连接的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!