說明:一定要吧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 memory | ctypes當中的類型,通過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()
|