有很多主題涉及標題的一部分,但沒有什麼能完全滿足整個事情。我正在推送遠程服務器上的命令,並且需要長時間執行完整輸出,比如5分鐘左右。使用通道我可以設置超時,但是當我讀回標準輸出時,我只獲得了一小部分輸出。解決方案似乎是等待channel.exit_status_ready()。這對一個成功的通話起作用,但失敗的通話永遠不會觸發通道超時。在審閱了文檔之後,我推理這是因爲超時只適用於讀取操作,並且等待退出狀態不合格。這是企圖:Python Paramiko超時執行時間很長,需要全部輸出
channel = ssh.get_transport().open_session()
channel.settimeout(timeout)
channel.exec_command(cmd) # return on this is not reliable
while True:
try:
if channel.exit_status_ready():
if channel.recv_ready(): # so use recv instead...
output = channel.recv(1048576)
break
if channel.recv_stderr_ready(): # then check error
error = channel.recv_stderr(1048576)
break
except socket.timeout:
print("SSH channel timeout exceeded.")
break
except Exception:
traceback.print_exc()
break
漂亮,是不是?祝它工作。
我第一次嘗試解決方案是使用time.time()獲取開始,然後檢查start - time.time()> timeout。這看起來很簡單,但在我現在的版本中,我輸出的start - time.time()帶有一個固定的超時值,它應該會觸發一箇中斷...並且看到不同的時間間隔,並且沒有中斷髮生時間的兩倍和三倍。爲了節省空間,我會提及我的第三次嘗試,這是我已經完成的。我在這裏讀到了關於使用select.select來等待輸出的信息,並在文檔中指出,那裏也有一個超時。正如你將從下面的代碼中看到的,我已經混合了所有三種方法 - 通道超時,time.time超時和選擇超時 - 但仍然需要終止進程。這裏的frankencode:
channel = ssh.get_transport().open_session()
channel.settimeout(timeout)
channel.exec_command(cmd) # return on this is not reliable
print("{0}".format(cmd))
start = time.time()
while True:
try:
rlist, wlist, elist = select([channel], [], [],
float(timeout))
print("{0}, {1}, {2}".format(rlist, wlist, elist))
if rlist is not None and len(rlist) > 0:
if channel.exit_status_ready():
if channel.recv_ready(): # so use recv instead...
output = channel.recv(1048576)
break
elif elist is not None and len(elist) > 0:
if channel.recv_stderr_ready(): # then check error
error = channel.recv_stderr(1048576)
break
print("{0} - {1} = {2}".format(
time.time(), start, time.time() - start))
if time.time() - start > timeout:
break
except socket.timeout:
print("SSH channel timeout exceeded.")
break
except Exception:
traceback.print_exc()
break
這裏的一些典型輸出:
[<paramiko.Channel 3 (open) window=515488 -> <paramiko.Transport at 0x888414cL (cipher aes128-ctr, 128 bits) (active; 1 open channel(s))>>], [], []
1352494558.42 - 1352494554.69 = 3.73274183273
頂行是[RLIST,wlist,ELIST]從選擇,底線是了time.time() - 開始=( time.time() - 開始)。循環1000次後,我通過計算迭代次數並在嘗試的底部打破了這個運行。樣品運行中超時設置爲3。這證明我們可以通過嘗試,但顯然,三種應該超時的方式都不適用。
如果我從根本上誤解了某些東西,隨意翻閱代碼。我希望這是超級Pythonic,我仍然在學習。
我的研究運行在相同的方向,但我得到「ValueError:信號只能在主線程中工作」,雖然我不是故意在我的代碼中使用線程。無論是某個模塊分叉進程或這是一個錯誤。思考? – user1772459
是的,我意識到python只支持主線程中的信號。如果你得到這個消息,那麼我猜想某些事情會產生線索。 –