【问题标题】:Python: Execute a command in Cisco Router on successful ping else print errorPython:在成功 ping 时在 Cisco 路由器中执行命令,否则打印错误
【发布时间】:2014-01-02 09:15:30
【问题描述】:

以下代码从文本文件中获取 IP 地址(Cisco 路由器)并执行上述命令并将结果输出打印到文件中。这里我尝试首先使用 PING 测试设备的可达性,成功的 ping 响应命令应该被执行,否则应该打印一个错误并移动到下一个主机。请帮助我如何实现这一目标。我是新手。

这是我的代码,

import paramiko
import sys
import os
import subprocess

with open('C:\Python27\Testing\Fetch.txt') as f:
    for line in f:
        line = line.strip()
        dssh = paramiko.SSHClient()
        dssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        dssh.connect(line, username='cisco', password='cisco')
        stdin, stdout, stderr = dssh.exec_command('sh ip ssh')
        mystring = stdout.read()
        print mystring
        f = open('C:\Python27\Testing\output.txt', 'a+')
        f.write(mystring)
        f.close()      
dssh.close()

输入文件 Fetch.txt 长这样,

10.0.0.1
10.0.0.2
10.0.0.3
10.0.0.4
10.0.0.5

我浏览了论坛并获得了我正在寻找的内容。如果该列表中的所有 IP 地址都可以访问,那么脚本就可以正常工作。但是,如果任何一个 IP 地址无法访问,则脚本会突然结束,而不会继续执行下一个 IP 地址。我意识到这里做错了,我只需要一点点帮助就可以让它工作......请帮忙。

import paramiko
import sys
import os
import subprocess
dssh = paramiko.SSHClient()
dssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())

with open('C:\Python27\Testing\Fetch.txt') as f:
     for line in f:
        line = line.strip()
        with open(os.devnull, "wb") as limbo:
            ip = line
            result = subprocess.Popen(["ping", "-n", "1", "-w", "200", ip],
                                      stdout=limbo, stderr=limbo).wait()
            if result: 
                    print ip, "Down"   
            else:   
                    print ip, "Reachable"  
    dssh.connect(line, username='cisco', password='cisco')
    stdin, stdout, stderr = dssh.exec_command('sh ip ssh')
    mystring = stdout.read()
    print mystring
    f = open('C:\Python27\Testing\output.txt', 'a+')
    f.write('\n' + ip + '\n' + mystring)
    f.close()      
dssh.close()

【问题讨论】:

  • 你能修复以 dssh.connect() 开头的部分的缩进吗?这样看起来它失败了,因为 ssh 连接代码在 for 循环之外。这样它总是在最终主机上执行,无论它是向上还是向下。我确定它应该在 else: block 中
  • 非常感谢。你的建议奏效了......
  • 路由器等嵌入式设备特有的一个问题:它们通常不实现整个 SSH 协议。 exec_command(),当你在这里使用它时,只有当 ssh router_ip "sh ip ssh" 也可以工作时才会工作——如果你不能从 OpenSSH 客户端成功运行它(使用命令行上的命令,连接后没有输入),那么这个 Paramiko 代码也不起作用。
  • ...如果这不起作用,您需要改用invoke_shell(),并使用类似期望的逻辑来等待提示、发送命令字符串等.

标签: python output ping paramiko cisco


【解决方案1】:

理想情况下,您不必首先使用单独的 if 语句来测试主机是否可 ping。paramiko 内置了许多异常检查 ..在套接字模块中使用它..您的程序可以编写成更简洁的时尚,无需使用子流程..

import paramiko
import socket
dssh = paramiko.SSHClient()
dssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ips = [i.strip() for i in open("C:\Python27\Testing\Fetch.txt")] # creates a list from input file

for ip in ips:
    try:
        dssh.connect(ip, username='cisco', password='cisco', timeout=4)
        stdin, stdout, stderr = ssh.exec_command('sh ip ssh')
        print ip + '===' + stdout.read()
        ssh.close()
    except paramiko.AuthenticationException:
        print ip + '=== Bad credentials'
    except paramiko.SSHException:
        print ip + '=== Issues with ssh service'
    except socket.error:
        print ip + '=== Device unreachable' 

这将捕获其他异常,例如凭据错误和 ssh 服务的其他问题

【讨论】:

    【解决方案2】:

    您可以尝试使用用于在多台机器上执行 SSH 命令的结构。

    这只是我拼凑的一个 sn-p,但它应该会告诉你要走的路。

    from fabric.api import run, execute ,env
    
    class Fetcher:
      def __init__(self,hosts=[]):
        env.hosts= hosts
        env.warn_only = True  # needed to not abort on pingtimout or other errs
    
      def getclock(self)
        run('sh clock')
    
      def fetch(self):
        results = execute(self.getclock,hosts=env.hosts)
    
    
    if __name__ == '__main__':
      hosts = loadfromtxt(hosts.txt)
      f = Fetcher(hosts=hosts)
      f.fetch()
    

    【讨论】:

    • 感谢您的回复。我对代码进行了一些更改,您可能可以就此提出建议。
    • " [Errno 10060] 连接尝试失败,因为连接方在一段时间后没有正确响应,或者建立连接失败,因为连接的主机没有响应“我收到提到的错误和代码在这里突然结束,我只想让 python 打印为主机“Down”并继续检查下一个主机并执行命令。
    【解决方案3】:

    我记得一个 python 线程的例子,无论是在文档中还是在我读过的一本书(不记得来源)中,它的作用类似于您正在尝试做的事情。像这样的东西应该可以工作:

    import sys
    import os
    import subprocess
    from threading import Thread
    
    class Pinger(Thread):
        def __init__ (self, ip):
            Thread.__init__(self)
            self.ip = ip
            self.status = False
    
        def __repr__(self):
            return "Pinger for '%s' status '%s'" % (self.ip, self.status)
    
        def run(self):
            with open(os.devnull, "wb") as limbo:
                # Changed the arguments because I don't have a windows ping.exe to test it on
                result = subprocess.Popen(["ping", "-c", "2", "-q", self.ip],
                                          stdout=limbo, stderr=limbo).wait()
                if result: 
    #                print self.ip, "Down"   
                    self.status = False
                else:   
    #                print self.ip, "Reachable"  
                    self.status = True
    
    
    hosts = []
    with open('Fetch.txt') as f:
        for line in f:
            host = Pinger(line.rstrip())
    #        print host
            hosts.append(host)
            host.start()
    
    for host in hosts:
        host.join()
        if host.status:
            print "Host '%s' is up" % host.ip
            #### Insert your ssh exec code here ####
            # dssh.connect(host.ip, username='cisco', password='cisco')
            # etc.
        else:    
            print "Host '%s' is down" % host.ip
    

    【讨论】:

    • @RyPeck 解决了我的问题。 @Mzzl 我会尝试您的建议并回复您。谢谢。
    【解决方案4】:

    如果 python 可以自己做,为什么需要 Paramiko 模块或创建输入?

    #!/usr/bin/python
    
    import os
    
    hostname = raw_input('Enter the Router Name: ')
    routers = hostname.split(',')
    print routers
    
    for hostname in routers:
            response = os.system("ping -c5 " + hostname) 
            if response == 0:
                print(hostname, 'is up!')
            else:
                print(hostname, 'is down!')
    

    【讨论】:

    • 因为paramiko是SSH客户端,命令要通过SSH执行命令。 ping 只是 OP 尝试做的一半。
    • 这是一个古老的查询,在论坛成员的帮助下得到了解决。谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-29
    • 1970-01-01
    • 2012-02-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多