python_多进程_paramiko+mulitProcess


Skip to end of metadata

说明:一定要吧ssh连接放在multiprocess的要处理的方法内部,否则会报错

将ssh连接的创建放到if 中,(在),程序报错:  Success for unrequested channel! [??]

import paramiko
from multiprocessing import Process,Queue
import os
 
def sshconnect(hostname,username,password):
    ssh=paramiko.SSHClient()
    ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy)
    ssh.connect(hostname=hostname,username=username,password=password,port=22)
    return ssh
def excute_command(ssh,cmd):
 
    print('cmd is '+ cmd)
    stdin,stdout,stderro=ssh.exec_command(cmd)
    results = stdout.read().decode()
    print(results)
    return results
 
 
if __name__=='__main__':
    hostname = '10.69.141.11'
    username = 'ubuntu'
    password = 'test1234'
    ssh = sshconnect(hostname=hostname, username=username,password=password)
    p=Process(target=excute_command,args=(ssh,'ls -al'))
    p.start()
    p.join()

 

说明:怀疑在父进程中创建的连接,子进程不能使用,顾在创建Process实例时,创建ssh连接,但是还是报同样的错误:Success for unrequested channel! [??]  :

 

if __name__=='__main__':
    hostname = '10.69.141.11'
    username = 'ubuntu'
    password = 'test1234'
    p=Process(target=excute_command,args=(sshconnect(hostname=hostname, username=username,password=password),'ls -al'))
    p.start()
    p.join()

在网上找到的一些资料, 感觉有可能就是子进程没有继承父进程的远程连接信息,:http://blog.ftofficer.com/2009/12/python-multiprocessing-2-object-sharing-across-process/

 

在mulitProcess库当中,跨进程对象共享有三种方式,第一种仅适用于原生机器类型,即python.ctypes当中的类型,这种在mp库的文档当中称为shared memory方式,即通过共享内存共享对象;另外一种称之为server process,即有一个服务器进程负责维护所有的对象,而其他进程连接到该进程,通过代理对象操作服务器进程当中的对象;最后一种在mp文档当中没有单独提出,但是在其中多次提到,而且是mp库当中最重要的一种共享方式,称为inheritance,即继承,对象在父进程当中创建,然后在父进程是通过multiprocessing.Process创建子进程之后,子进程自动继承了父进程当中的对象,并且子进程对这些对象的操作都是反映到了同一个对象。

这三者共享方式各有特色,在这里进行一些简单的比较。

首先是共享方式所应对的对象类型,看这个表:

共享方式支持的类型
Shared memoryctypes当中的类型,通过RawValue,RawArray等包装类提供
Inheritance系统内核对象,以及基于这些对象实现的对象。包括Pipe, Queue, JoinableQueue, 同步对象(Semaphore, Lock, RLock, Condition, Event等等)
Server process所有对象,可能需要自己手工提供代理对象(Proxy)

这个表总结了三种不同的共享方式所支持的类型,下面一个个展开讨论。

其中最单纯简单的就是shared memory这种方式,只有ctypes当中的数据类型可以通过这种方式共享。由于mp库本身缺少命名的机制,即在一个进程当中创建的对象,无法在另外一个进程当中通过名字来引用,因此,这种共享方式依赖于继承,对象应该由父进程创建,然后由子进程引用。关于这种机制的例子,可以参见Python文档当中的例子 Synchronization types like locks, conditions and queues,参考其中的test_sharedvalues函数。

然后是继承方式。首先关于继承方式需要有说明,继承本质上并不是一种对象共享的机制,对象共享只是其副作用。子进程从父进程继承来的对象并不一定是共享的。继承本质上是父进程fork出的子进程自动继承父进程的内存状态和对象描述符。因此,实际上子进程复制了一份父进程的对象,只不过,当这个对象包装了一些系统内核对象的描述符的时候,拷贝这个对象(及其包装的描述符)实现了对象的共享。因此,在上面的表当中,只有系统内核对象,和基于这些对象实现的对象,才能够通过继承来共享。通过继承共享的对象在linux平台上没有任何限制,但是在Windows上面由于没有fork的实现,因此有一些额外的限制条件,因此,在Windows上面,继承方式是几乎无法用的。

解决办法:

将ssh连接的创建放到excute_command ,程序可以正常运行

import paramiko
from multiprocessing import Process,Queue
import os
 
def sshconnect(hostname,username,password):
    ssh=paramiko.SSHClient()
    ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy)
    ssh.connect(hostname=hostname,username=username,password=password,port=22)
    return ssh
def excute_command(hostname,username,password,cmd):
    ssh = sshconnect(hostname=hostname, username=username,password=password)
    print('cmd is '+ cmd)
    stdin,stdout,stderro=ssh.exec_command(cmd)
    results = stdout.read().decode()
    print(results)
    return results
 
 
if __name__=='__main__':
    hostname = '10.69.141.11'
    username = 'ubuntu'
    password = 'test1234'
    p=Process(target=excute_command,args=(hostname,username,password,'ls -al'))
    p.start()
    p.join()

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章