Có rất nhiều chủ đề được chạm vào một phần của tiêu đề, nhưng không có gì hoàn toàn thỏa mãn toàn bộ. Tôi đang đẩy một lệnh trên một máy chủ từ xa và cần đầu ra đầy đủ sau một thời gian thực hiện dài, nói rằng 5 phút hoặc lâu hơn. Sử dụng kênh tôi đã có thể thiết lập một thời gian chờ, nhưng khi tôi đọc trở lại stdout tôi chỉ nhận được một phần nhỏ của đầu ra. Giải pháp dường như chờ channel.exit_status_ready(). Điều này làm việc trên một cuộc gọi thành công, nhưng một cuộc gọi không thành công sẽ không bao giờ kích hoạt thời gian chờ của kênh. Sau khi xem xét các tài liệu, tôi giả định đó là vì thời gian chờ chỉ hoạt động trên một hoạt động đọc và chờ trạng thái thoát không đủ điều kiện. Đây là nỗ lực đó:Thời gian chờ của Python Paramiko với thời gian thực thi dài, cần có đầu ra đầy đủ
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
Khá, phải không? Muốn nó hoạt động.
Nỗ lực đầu tiên của tôi tại giải pháp là sử dụng time.time() để bắt đầu, sau đó kiểm tra start - time.time()> timeout. Điều này có vẻ đơn giản, nhưng trong phiên bản hiện tại của tôi, tôi xuất đầu - time.time() với thời gian chờ cố định sẽ kích hoạt ngắt ... và thấy sự khác biệt gấp đôi và gấp ba lần thời gian chờ mà không xảy ra sự cố. Để tiết kiệm không gian, tôi sẽ đề cập đến nỗ lực thứ ba của tôi, mà tôi đã cuộn lên với cái này. Tôi đọc ở đây về việc sử dụng select.select để chờ đầu ra, và lưu ý trong tài liệu có thời gian chờ ở đó. Như bạn sẽ thấy từ mã bên dưới, tôi đã trộn cả ba phương thức - thời gian chờ của kênh, thời gian chờ time.time và chọn thời gian chờ - nhưng vẫn phải giết quá trình. Đây là 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
Dưới đây là một số kết quả tiêu biểu:
[<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
Dòng đầu là [rlist, wlist, elist] từ chọn, điểm mấu chốt là time.time() - start = (time.time() - bắt đầu). Tôi đã chạy này để phá vỡ bằng cách đếm các lần lặp và phá vỡ ở dưới cùng của thử sau khi lặp 1000 lần. thời gian chờ được đặt thành 3 khi chạy mẫu. Điều đó chứng minh rằng chúng tôi vượt qua được thử thách, nhưng rõ ràng, không có cách nào trong ba cách đó là thời gian hoạt động.
Hãy thoải mái trích xuất mã nếu tôi đã hiểu sai về cơ bản điều gì đó. Tôi muốn cho điều này là uber-Pythonic và vẫn đang học.
Nghiên cứu của tôi chạy theo cùng một hướng, nhưng tôi nhận được "ValueError: tín hiệu chỉ hoạt động trong chuỗi chính", mặc dù tôi không cố ý sử dụng các chuỗi trong mã của mình. Hoặc là một số mô-đun đang thúc đẩy quá trình hoặc đây là lỗi. Suy nghĩ? – user1772459
Vâng, tôi nhận ra rằng python chỉ hỗ trợ tín hiệu trong chuỗi chính. Nếu bạn nhận được thông điệp đó, thì tôi đoán có gì đó sinh ra các chủ đề tại một thời điểm nào đó. –