ping response via paramiko

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
Fenrir
User
Beiträge: 13
Registriert: Sonntag 2. April 2017, 10:33

Hallo Leute,

Hab wieder mal ein kleines Probem.
Und zwar connecte ich via paramiko auf einen rechner und fuehre mit exec_command einen Ping-Befehl, was auch alles soweit ganz gut klappt, allerdings habe ich Schwierigkeiten, die Antwort zu interpretieren. Mit subprocess habe ich ein aehnliches script, bei dem ich nicht auf dieses Problem treffe.

Code: Alles auswählen

import time
import paramiko


def sshPing(destination, ip):
    try:
        client = paramiko.SSHClient()
        client.load_system_host_keys()
        client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        client.connect(destination, port=22, username="root", key_filename="/root/.ssh/id_rsa")

        command = "ping -c 1 " + str(ip) # + " > /dev/null 2>&1" 
        response = 0

        while response == 0:
            (stdin, stdout, stderr) = client.exec_command(command)
            if not stdout.read():
                response = 1
                print('ip is up')
            else:
                print('ip is not reachable yet')
                time.sleep(5)
    finally:
        client.close()

sshPing('192.168.1.55', '192.168.2.27')
so wie der code ist, bekomm ich immer False, auch wenn die ip an sich pingbar ist.
Hab schon einiges versucht, aber entweder immer True oder immer False.
Wenn ich stdout.read() ausgeben lasse, dann bekomm ich auch das zueruck was kommen soll, allerdings weiss ich nicht wie ich es interpretieren kann. Den output string nach "error" zu filtern waere noch das einzige, dass mir einfaellt.
Vll hatte ja von euch schonmal jmd so nen Fall...

Danke fuer eure Ideen und Hilfe schonmal :)

PS: Muss ueber paramiko bzw ssh pingen, da die Architektur meines Netzwerkes leider kein forwarding etc erlaubt.

Edit: sry, falsches Unterforum, gehoert wohl in Netzwerkprogrammierung....
Benutzeravatar
sls
User
Beiträge: 480
Registriert: Mittwoch 13. Mai 2015, 23:52
Wohnort: Country country = new Zealand();

Fenrir hat geschrieben:

Code: Alles auswählen

            (stdin, stdout, stderr) = client.exec_command(command)
            if not stdout.read():
                response = 1
                print('ip is up')
            else:
                print('ip is not reachable yet')
                time.sleep(5)
Wenn ich stdout.read() ausgeben lasse, dann bekomm ich auch das zueruck was kommen soll, allerdings weiss ich nicht wie ich es interpretieren kann.
stdout ist eigentlich der Kanal, an dem erfolgreiche Meldungen ausgegeben werden. Eigentlich bewirkt doch deine IF-Bedingung genau das Gegenteil: "Falls nicht stdout (erfolgreich) -> IP ist erreichbar"

Wie lautet denn die genaue Meldung, wenn du via print den Inhalt von stdout.read() anzeigen lässt?
When we say computer, we mean the electronic computer.
Fenrir
User
Beiträge: 13
Registriert: Sonntag 2. April 2017, 10:33

@sls
Danke fuer die Antwort.
Das mit dem 'not' ist dann im Laufe der Tests da so stehen geblieben, aber das spiet fuer mein Problem auch keine Rolle.
Es geht ja darum, dass ich aus dem stdout gerne auf True oder False kommen wuerde, fuer erreichbar und nicht erreichbar, aber keine Ahung hab wie man das am besten macht.

Hier mal der output von

Code: Alles auswählen

print(stdout.read())
b'PING 192.168.2.37 (192.168.2.37) 56(84) bytes of data.\nFrom 192.168.2.26 icmp_seq=1 Destination Host Unreachable\n\n--- 192.168.2.37 ping statistics ---\n1 packets transmitted, 0 received, +1 errors, 100% packet loss, time 0ms\n\n'
ip is up!
b'PING 192.168.2.27 (192.168.2.27) 56(84) bytes of data.\n64 bytes from 192.168.2.27: icmp_seq=1 ttl=64 time=0.415 ms\n\n--- 192.168.2.27 ping statistics ---\n1 packets transmitted, 1 received, 0% packet loss, time 0ms\nrtt min/avg/max/mdev = 0.415/0.415/0.415/0.000 ms\n'
ip is up!
Sowas hier wuerd ich in etwa suchen, response = 0 fuer erreichbar:

Code: Alles auswählen

response = os.system("ping -c 1 " + str(ip[0]) + " > /dev/null 2>&1")
aber mit paramiko hab ich nur command_exec gefunden zum ausfuerhen von Befehlen.


Hab es jetzt vorlaeufig mal mit dem string nach 'error' durchsuchen geloest, aber ist halt auch irgendwie bloed...
Benutzeravatar
sls
User
Beiträge: 480
Registriert: Mittwoch 13. Mai 2015, 23:52
Wohnort: Country country = new Zealand();

Die drei Kanäle stdin, stdout und stderr werden dir aber nicht die Logik abnehmen, ob der Befehl den du auf dem lokalen Host ausführen lässt, richtig oder falsch sind. Sie liefern dir lediglich die Antwort was auf dem lokalen Host passiert ist. Gibt es einen Fehler bei der Übertragung deiner Daten (bspw. dass der Zielhost gar nicht erreichbar ist), wird dies vom stderr-Kanal abgefangen.

Aus Python/Paramiko-Sicht ist ja alles in Ordnung: du sendest deinen Ping Befehl via SSH-Session und dieser wird auch ausgeführt. Ob der Zielhost via Ping nun erreichbar ist oder nicht, weiß Paramiko ja nicht. Die Auswertung dieser Daten musst du also selber durchführen.

Ein Ping ist eigentlich nicht das ultimative Mittel um die Erreichbarkeit von einem Zielhost zu ermitteln, schon gar nicht, wenn du nur ein einziges Paket abschickst. Hier würde ich eher min. 4 Pakete abschicken, dann sparst du dir auch das time.sleep(5).
When we say computer, we mean the electronic computer.
Sirius3
User
Beiträge: 17749
Registriert: Sonntag 21. Oktober 2012, 17:20

`exec_command` von client ist nur ein Wrapper für `channel.exec_command`, die darunterliegende API gibt auch Zugriff auf den ExitCode.

Code: Alles auswählen

import time
import paramiko

def ssh_ping(destination, ip):
    try:
        client = paramiko.SSHClient()
        client.load_system_host_keys()
        client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        client.connect(destination, port=22, username="root", key_filename="/root/.ssh/id_rsa")

        command = "ping -c 1 {} >/dev/null 2>&1".format(ip)
        while True:
            chan = client.get_transport().open_session()
            chan.exec_command(command)
            if chan.recv_exit_status() == 0:
                # no error
                break
            print('ip is not reachable yet')
            time.sleep(5)
        print('ip is up')
    finally:
        client.close()

ssh_ping('192.168.1.55', '192.168.2.27')
Fenrir
User
Beiträge: 13
Registriert: Sonntag 2. April 2017, 10:33

@Sirius3

Genau das hab ich gesucht, vielen vielen Dank :)
Antworten