Python Paramiko挂在.recv(1024)

时间:2018-07-15 23:28:42

标签: python python-2.7 paramiko

我在使用invoke shell接收来自特定命令的输出时遇到问题。该脚本的目的是登录并检查linux / unix服务器上特定应用程序的状态。问题源于服务器列表庞大,并且并非所有服务器都具有该应用程序。因此,该脚本可在具有该应用程序的服务器上运行,甚至可以拉取数据并将其打印到屏幕上,但是当脚本出现“ -bash:CMD:未找到命令”时,该脚本将挂起,并且不会遍历列表。 / p>

我还确认使用wireshark和过滤服务器的IP ip.addr == x.x.x.x TCP连接已建立,因此排除了该路径上的任何ACL,FW和/或IP表。由于wireshark中的数据包已加密,因此我无法进一步详细说明。

我可以看到服务器与我的桌面(客户端)进行通信,并发送多个镜头的多个加密数据包。该脚本似乎挂在打印语句之前(卡住了)。

现在最理想的情况是使用exec shell,但是我希望将此脚本设计为将来可伸缩。

我以前在网络设备甚至服务上使用过此脚本,当预期的响应具有统一的含义,显示路由,uname -a时,这些脚本都可以工作,但是这些都是预期的结果,但是我认为其中有些不同到bash没有命令错误,导致接收问题。

# ***** Open Plain Text
f = open("nfsus.txt")

# ***** Read & Store into Variable
hn=(f.read().splitlines())
f.close()

# ***** Credentials 
#username =  raw_input("Please Enter Username: ")
#password =  getpass.getpass("Please Enter Passwod: ")


# ***** SSH
client=paramiko.SSHClient()

def connect_ssh(hn):
    try:
        client.load_system_host_keys()
        client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        client.connect(hn, 22, username, password, look_for_keys=False, allow_agent=False)

        print 'Connection Attempting to: '+(hn)
        channel = client.get_transport().open_session()
        channel.invoke_shell()



        channel.sendall("CMD \n")
        cmd = channel.recv(1024)

        #SCRIPT HANGS HERE! ^
        print ('stuck')

        #print (cmd)

    except Exception, e:
        print '*** Caught exception: %s: %s' % (e.__class__, e)
    try:
        channel.close()
    except:
        pass

# *****Create Loop through input.txt (contains a list of IP address)
for x in hn:
    connect_ssh(x)

我是Python新手,并且承认,我很难受!但是,我确实尽最大的努力来理解脚本的每个细节。我一生中从未用python或任何其他语言写过任何东西。我很高兴学习,但是请耐心等待,因为我很烂!我仔细阅读了paramiko文档,但是有些事情我还没有完全理解,我希望这里的人足够酷,可以向这个菜鸟展示我的方式的错误。

谢谢

1 个答案:

答案 0 :(得分:1)

在狗狗时代,我还没有看过Paramiko,但是在这种情况下,bash(shell)在“ STDERR”而不是“ STDOUT”上发送错误消息。可能是Paramiko没有在听STEDRR,所以它没有收到错误消息,或者是以其他方式捕获它们。

ortep@Motte ~
$ foobar
-bash: foobar: command not found

ortep@Motte ~
$ foobar 2>/dev/null
ortep@Motte ~
$

在第二次调用“ foobar”时,我将(>)STDERR(2)重定向到/ dev / null设备。

您还可以将其重定向到“ STDOUT”:

ortep@Motte ~
$ foobar 2>&1
-bash: foobar: command not found

这看起来是一样的,因为在ssh控制台上,STDOUT和STDERR是(相同的)东西。

因此,这给了您两个可能有所帮助的选择。一种方法是:

channel.sendall("CMD 2>&1 \n")

另一种是检查命令是否存在:

channel.sendall("if [[-x /path/to/CMD ]]; then /path/to/CMD/; else echo "CMD not found"; fi \n) 

第一个更容易尝试,第二个可以在“ else”部分扩展以提供更多信息(例如“;否则,回显“ CMD不在$(hostname)上”)。有用)。