python多处理paramiko

python多处理paramiko

本文介绍了python多处理paramiko ssh连接的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在编写一个脚本来连接到一堆 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连接的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-15 19:40