【问题标题】:Prevent Paramiko from Exiting防止 Paramiko 退出
【发布时间】:2017-02-11 13:30:53
【问题描述】:

说明

我正在尝试编写一个 python 脚本以通过 SSH 连接到我的虚拟机并执行一些命令。

  • 如果我手动执行此操作,我的会话将保持打开状态,并且我仍然可以看到我的实时日志

  • 如果我使用脚本,在 SSH 进入并自动执行一些命令后,它会不断退出并返回到我的用户提示符。我正在努力防止这种情况发生。


视频

手动 = https://dl.dropboxusercontent.com/u/56134944/ssh_wag_manually.mov

通过 Python 脚本 = https://dl.dropboxusercontent.com/u/56134944/ssh_wag_py.mov


这就是我现在拥有的

import paramiko
import time
import sys

# Note
# sudo pip install --user paramiko


def ssh_con (ip, un, pw):
    global client
    client = paramiko.SSHClient()
    client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    print ("Connecting to device/VM: %s" % ip)
    client.connect(ip, username=un, password=pw)


def cmd_io (command):
    global client_cmd
    client_cmd.send("%s \n" %command)
    time.sleep(1)
    output = client_cmd.recv(10000).decode("utf-8")
    print (output)

# ip = raw_input("Enter WAG IP : ")
# ip  = sys.argv[1]

ip = '172.168.200.300'
un = 'xyz'
pw = 'abc'

ssh_con(ip,un,pw)
client_cmd = client.invoke_shell()

print ("SSH CONNECTION ESTABLISHED TO vMEG %s" % ip)
cmd_io ("en")
cmd_io ("terminal monitor")
cmd_io ("debug wag https")
cmd_io ("debug wag httpc")
cmd_io ("debug https")
cmd_io ("debug httpc")
cmd_io ("debug wag kafka")

结果

[local]site#
terminal monitor 
[local]site#
debug wag https 
[local]site#
debug wag httpc 
[local]site#
debug https 
[local]site#
debug httpc 
[local]site#
debug wag kafka 
[local]site#

.... Quitting and return the command prompt ....

──[/Applications/MAMP/htdocs/code/python] 
└── 

如何防止这种情况发生?

【问题讨论】:

  • SSH 会话何时退出:立即退出,或在一定时间后,或在您输入命令后,或其他?
  • 基本上在完成脚本的最后一行之后...
  • 好吧,你的脚本正在结束,所以自然会关闭进程打开的任何 TCP 连接。您希望脚本继续运行吗?您是否希望 ssh 连接以某种方式在脚本退出后仍然存在?在所有命令执行完毕后,你想对这个 ssh 会话做什么?
  • 我希望脚本继续运行,让带有这些命令的 SSH 窗口保持打开状态,并且不返回提示,直到我输入 exit
  • @Kenster :进程打开的任何 TCP 连接自然都会关闭,我不知道。

标签: python ssh terminal paramiko


【解决方案1】:

将此函数放在脚本的顶部

def write_and_print_logs(log_message):
    with open("debugLogs.txt", 'a') as logs:
        logs.write("{}\n".format(log_message))
    print(log_message)

现在将每个print(<message>) 命令替换为write_and_print_logs(<message>)。现在所有内容都将写入文件,无论您是否实时查看日志,您都可以打开它并查看发生了什么。

【讨论】:

    【解决方案2】:

    您的主要问题是您只是停止读取 paramiko 的输出。如果您希望程序继续等待 VM 的进一步输出,您需要告诉它这样做。例如,这应该可以解决问题:

    import paramiko
    import time
    import sys
    import socket
    
    # Note
    # sudo pip install --user paramiko
    
    
    def ssh_con (ip, un, pw):
        global client
        client = paramiko.SSHClient()
        client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        print ("Connecting to device/VM: %s" % ip)
        client.connect(ip, username=un, password=pw)
    
    
    def cmd_io (command):
        global client_cmd
        client_cmd.send("%s \n" %command)
        time.sleep(1)
        output = client_cmd.recv(10000).decode("utf-8")
        print (output)
    
    # ip = raw_input("Enter WAG IP : ")
    # ip  = sys.argv[1]
    
    ip = '172.168.200.300'
    un = 'xyz'
    pw = 'abc'
    
    ssh_con(ip,un,pw)
    client_cmd = client.invoke_shell()
    
    print ("SSH CONNECTION ESTABLISHED TO vMEG %s" % ip)
    cmd_io ("en")
    cmd_io ("terminal monitor")
    cmd_io ("debug wag https")
    cmd_io ("debug wag httpc")
    cmd_io ("debug https")
    cmd_io ("debug httpc")
    cmd_io ("debug wag kafka")
    
    client_cmd.settimeout(1.0)
    while True:
        try:
            output = client_cmd.recv(10000).decode("utf-8")
            print (output)
        except socket.timeout:
            pass
    

    但是,这并不能解决所有问题。您的脚本还应该更严格地处理可能的错误情况。例如,它应该读取 stderr 流,检查通道是否实际上已经关闭,并且做的不仅仅是等待每个命令完成 1 秒。

    如果它只是一个快速脚本,那么缺少错误处理可能一切都很好。但是,如果您需要它 100% 可靠地工作,您将需要在某个时候解决它们。

    【讨论】:

    • 首先非常感谢您的回答、解释和建议,效果很好。不过,我有几个问题。
    • 1. you may need to add extra sends to that loop if pressing enter,额外发送是什么意思?
    • 你正在使用一个 SSH 客户端,所以你 send 对 VM 的任何命令和 recv 它的任何输出。您的视频中不清楚是否仅使用 recv 会起作用,或者您是否需要定期发送新线路。该代码的确切含​​义包含在docs.paramiko.org/en/2.0/api/channel.html
    • 澄清一下,我不需要发送任何新行,在我的最后一个命令 `debug wag kafka` 之后,这就是我所需要的。感谢您就此事回复我。我注意到我不能用Ctrl+CCtrl+D 杀死窗口......我想和你核实一下。我需要在我的 python 脚本中处理它吗?如果您可以将我的其余 python 代码与您的作为您惊人答案的一部分结合起来,那就太好了。 :D
    • OK - 那是因为我过度简化了代码并且它在 recv 命令中被阻塞了。我已经更新了答案,可以让你按 Ctrl-C 来杀死它。
    猜你喜欢
    • 1970-01-01
    • 2017-10-23
    • 2010-10-09
    • 2012-07-26
    • 2018-11-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多