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()

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