Featured image of post Python Ping, un script que revisa las direcciones IP de tu red

Python Ping, un script que revisa las direcciones IP de tu red

Python Ping es un pequeño programa que repasa los elementos de la red y te avisa si están o no activos. La mejor forma de aprender un lenguaje de programación es tomando un proyecto y resolviendo sus problemas, este puede ser un buen caso de estudio.

La mejor forma de aprender un lenguaje de programación es tomando un proyecto y resolviendo sus problemas. En el proceso se investiga como hacer las cosas, resolver algunas dudas, depurar el código y probar su funcionalidad.

Soy fan de Python, pero no soy un experto. Python Ping es un programa que toma un archivo CSV (delimitado por comas) que tiene dos datos, una descripción del equipo y su dirección IP.

El programa toma esa información y hace ping, si el equipo responde, muestra un mensaje de OK, de lo contrario, reproduce un sonido y muestra un mensaje de error.

Hace una pausa de 10 minutos y vuelve a empezar. De esa forma es posible detectar problemas en la red, su ubicación y su frecuencia.

En una operación normal, todo debería de estar OK, pero todos sabemos que eso no siempre es así.

El archivo CSV.

Lo bonito de almacenar la información en un archivo CSV  es que es muy sencillo de editar, actualizar y mantener.

Para ejemplo de este artículo elegí servidores que todos conocemos:

Archivo servidores.csv

Google , google.com
Bing , bing.com
Facebook , facebook.com
Twitter , twitter.com
Wikipedia , wikipedia.com

Una descripción, luego una coma y al final una dirección. Para el ejemplo puse los dominios, pero se pueden reemplazar por las direcciones IP. Eso lo hago porque a mi me interesa revisar una red local.

Desmenuzando el programa.

Al final del artículo pondré el código completo, aquí voy a ir desmenuzando algunas de las partes del mismo.

Import

import os
import csv
from colorama import Fore
import time
import datetime

Esta es la lista de los import del programa. Para que algunas cosas funcionen es necesario declararlas primero.

os lo utilizo para ejecutar instrucciones como si estuviera en la terminal.

csv para importar la información del archivo CSV en una variable dentro del programa.

colorama le da color, poniendo los errores en rojo, lo que esta bien en verde, los textos en blanco.

time y datetime los uso para formatear algunas salidas de tiempo.

check_ping

La función check_ping es la que hace el trabajo pesado. Quiero hacer notar que en lugar de utilizar el comando ping tradicional uso el comando fping  que es más rápido y se adapta mejor cuando se llama desde un script.

La instrucción fping hace 10 reintentos antes de declarar un error de conexión.

sonido_alerta

Esta función es un plus. No voy a estar viendo la pantalla todo el tiempo durante la ejecución del script. Así que si hay un error hace un sonido. Como pueden ver en el código, lo que hace es reproducir un archivo mp3 a su elección.

El loop

El programa se repite indefinidamente en un ciclo haciendo una pausa de 10 minutos. De esta forma está revisando continuamente la red y avisa si hay algún problema. Para terminar el ciclo hay que presionar Control + C y se interrumpe la ejecución.

#!/usr/bin/python3

# python_ping.py - Hace ping a ciertos elementos de la red.
# ---------------------------------------------------------
# Este programa es software libre. Puede redistribuirlo y/o
# modificarlo bajo los términos de la Licencia Pública General
# de GNU según es publicada por la Free Software Foundation,
# bien de la versión 2 de dicha Licencia o bien (según su
# elección) de cualquier versión posterior.
#
# Este programa se distribuye con la esperanza de que sea
# útil, pero SIN NINGUNA GARANTÍA, incluso sin la garantía
# MERCANTIL implícita o sin garantizar la CONVENIENCIA PARA UN
# PROPÓSITO PARTICULAR. Para más detalles, véase la Licencia
# Pública General de GNU.
#
# Autor: LinuxmanR4 http://linuxmanr4.com
# versión 1.0
#

import os
import csv
from colorama import Fore
import time
import datetime

def check_ping(hostname):
    response = os.system("fping -r 10 -q " + hostname + " >/dev/null")
    if response == 0:
        check_ping = "[OK]"
    else:
        check_ping = "[Error]"

    return check_ping

def sonido_alerta():
    os.system("play -q ent_communicator1.mp3")

# Lee los datos del archivo y los guarda en una variable.
archivo_servidores = open('servidores.csv')
servidores_reader = csv.reader(archivo_servidores)
datos_servidores = list(servidores_reader)

# Prueba si hay conexión en todos los servidores
contador = 0

while True:
    for i in range(len(datos_servidores)):
        servidorTexto = datos_servidores[i][0]
        servidorIP = datos_servidores[i][1]
        resultado = check_ping(datos_servidores[i][1])

        if resultado == "[Error]":
            print("{0:30} {1:17} {2:7}".format(
                Fore.WHITE + servidorTexto, servidorIP, Fore.RED + resultado))
            sonido_alerta()
        else:
            print("{0:30} {1:17} {2:7}".format(
                Fore.WHITE + servidorTexto, servidorIP, Fore.GREEN + resultado))

    contador += 1
    print(Fore.BLUE)
    print('{0} {1:%H:%M:%S} {2}'.format(contador, datetime.datetime.now(),
                                    "________________________________________"))
    print()

    # Pausa de 10 minutos.
    time.sleep(600)
python\_ping en acción

python_ping en acción

Como pueden ver, el programa es relativamente sencillo. Estoy consciente de que hay muchas cosas que se pueden mejorar, así que estoy abierto a sus comentarios. Si desean utilizarlo, lo pueden hacer respetando claro la licencia pública general GNU, que permite utilizar, distribuir y modificar este código.

Python Ping la versión 2.0

Hace 7 años que publiqué este programa y funciono muy bien, pero en ese tiempo aprendí algunos trucos nuevos.

Por ejemplo, aprendí a manejar las dependencias con Poetry y eso me ayudó bastante, sobre todo durante las actualizaciones de Manjaro . También quise probar un enfoque más basado en funciones.

Esta nueva versión toma la información de un archivo CSV, ejecuta las pruebas y cuando termina muestra los resultados.

Da la apariencia de que se ejecuta más rápido, pero la verdad es que solo está trabajando desde un segundo plano.

#!/usr/bin/python3

import csv
from colorama import Fore
import time
import datetime
import subprocess

# Obtener la lista de servidores del archivo CSV
with open('servidores.csv') as archivo_servidores:
    servidores_reader = csv.reader(archivo_servidores)
    datos_servidores = [(row[0], row[1]) for row in servidores_reader]

# Formatos de color
COLORES = {
    "ok": Fore.GREEN + "[OK]",
    "error": Fore.RED + "[Error]",
    "header": Fore.BLUE,
    "texto": Fore.WHITE
}

def verificar_estado_red():
    # Obtener todas las IPs de una vez
    ips = [servidor[1] for servidor in datos_servidores]

    estados = {}

    # Ejecutar un solo comando fping para todas las IPs
    try:
        resultado = subprocess.run(
            ['fping', '-r', '3'] + ips,
            stdout=subprocess.PIPE,
            stderr=subprocess.STDOUT,
            text=True,
            check=False
        )
        estados = parsear_resultado_fping(resultado.stdout)
    except Exception as e:
        print(f"Error al ejecutar fping: {e}")

    imprimir_estados(estados)
    time.sleep(120)

def parsear_resultado_fping(output):
    # Parsear resultados de fping para crear diccionario de estados
    estados = {}
    for linea in output.split('\n'):
        if 'alive' in linea or 'unreachable' in linea:
            partes = linea.split()
            ip = partes[0]
            estado = "[OK]" if 'alive' in linea else "[Error]"
            estados[ip] = estado
    return estados

def imprimir_estados(estados):
    for nombre, ip in datos_servidores:
        estado = estados.get(ip, "[Error]")
        color = COLORES["ok"] if estado == "[OK]" else COLORES["error"]
        print(f"{COLORES['texto']}{nombre:25} {ip:17} {color}")

    tiempo_actual = datetime.datetime.now().strftime("%H:%M:%S")
    print(f"\n{COLORES['header']}{tiempo_actual} {'_'*40}\n")

if __name__ == "__main__":
    while True:
        verificar_estado_red()

La primera versión es más simple definitivamente. La segunda me parece más modular por el uso de las funciones.

¿A ustedes qué versión les gusta más?

Licensed under CC BY-NC-SA 4.0
Última actualización 10 may. 2018 510:00 CST
Todas las imágenes, nombres de productos y nombres de empresa o logotipos citados en esta página web son propiedad de sus respectivos propietarios.
Creado con Hugo
Tema Stack diseñado por Jimmy