Хобрук: Ваш путь к мастерству в программировании

Python: выполните команду в маршрутизаторе Cisco при успешном выполнении ping, иначе ошибка печати

Следующий код извлекает 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: 02.01.2014
  • Большое спасибо. Ваше предложение сработало...... 03.01.2014
  • Одна проблема, характерная для встроенных устройств, таких как маршрутизаторы: они часто не реализуют весь протокол SSH. exec_command(), как вы его используете здесь, будет работать только в том случае, если ssh router_ip "sh ip ssh" также будет работать - если вы не можете успешно запустить это из клиента OpenSSH (с командой в командной строке, не введенной после подключения), тогда этот код Paramiko выиграл тоже не работает. 17.04.2015
  • ... в случае, если это не сработает, вам нужно будет вместо этого использовать invoke_shell() и использовать логику, подобную ожидаемой, для ожидания приглашения, отправки командной строки и т. д. 17.04.2015

Ответы:


1

В идеале вам не нужно сначала проверять, доступен ли хост для проверки связи, используя отдельный оператор if.. 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.

03.11.2014

2

Вы можете попробовать использовать ткань, которая предназначена для выполнения команд SSH на нескольких машинах.

Это всего лишь фрагмент, который я собрал вместе, но он должен показать вам путь.

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()
02.01.2014
  • Спасибо за ответ. Я внес некоторые изменения в код, и, возможно, вы можете что-то посоветовать. 02.01.2014
  • [Errno 10060] Попытка подключения не удалась, потому что подключенная сторона не ответила должным образом через некоторое время, или установленное соединение не удалось, потому что подключенный хост не ответил. Я получаю указанную ошибку, и код внезапно заканчивается здесь, вместо этого я просто хочу python для печати как host Down и перейти к проверке следующего хоста и выполнить команду. 02.01.2014

  • 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
    
    02.01.2014
  • @ RyPeck решил мою проблему. @ Mzzl Я попробую ваше предложение и свяжусь с вами. Спасибо. 03.01.2014

  • 4

    Зачем вам модуль Paramiko или для создания ввода, если python может сделать сам?

    #!/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!')
    
    17.04.2015
  • Потому что paramiko — это SSH-клиент, и команда хочет выполнить команду через SSH. ping - это только половина того, что пытается сделать OP. 17.04.2015
  • Это старый запрос, и он работает с помощью участников форума. Спасибо. 20.04.2015
  • Новые материалы

    Создание кнопочного меню с использованием HTML, CSS и JavaScript
    Вы будете создавать кнопочное меню, которое имеет состояние наведения, а также позволяет вам выбирать кнопку при нажатии на нее. Финальный проект можно увидеть в этом Codepen . Шаг 1..

    Внедрите OAuth в свои веб-приложения для повышения безопасности
    OAuth — это широко распространенный стандарт авторизации, который позволяет приложениям получать доступ к ресурсам от имени пользователя, не раскрывая его пароль. Это позволяет пользователям..

    Классы в JavaScript
    class является образцом java Script Object. Конструкция «class» позволяет определять классы на основе прототипов с чистым, красивым синтаксисом. // define class Human class Human {..

    Как свинг-трейдеры могут использовать ИИ для больших выигрышей
    По мере того как все больше и больше профессиональных трейдеров и активных розничных трейдеров узнают о возможностях, которые предоставляет искусственный интеллект и машинное обучение для улучшения..

    Как построить любой стол
    Я разработчик программного обеспечения. Я люблю делать вещи и всегда любил. Для меня программирование всегда было способом создавать вещи, используя только компьютер и мое воображение...

    Обзор: Машинное обучение: классификация
    Только что закончил третий курс курса 4 часть специализации по машинному обучению . Как и второй курс, он был посвящен низкоуровневой работе алгоритмов машинного обучения. Что касается..

    Разработка расширений Qlik Sense с qExt
    Использование современных инструментов веб-разработки для разработки крутых расширений Вы когда-нибудь хотели кнопку для установки переменной в приложении Qlik Sense? Когда-нибудь просили..