How do I display if I can ping a machine without displaying the textual ping pollution itself?

Asked

Viewed 293 times

0

My code is printing ping output (that polluted screen), but I wanted to print only the default "{ip} ta on".

How you currently print:

PING 192.168.2.1 (192.168.2.1) 56(84) bytes of data.
64 bytes from 192.168.2.1: icmp_seq=1 ttl=64 time=1.54 ms...

I want you to print that way;

192.168.1.1 ta on

192.168.1.2 ta on

192.168.1.3 ta off

Code:

import os
os.system('clear')
ip = input('IP INICIAL (192.168.0.1); ').split('.')
print ('Testing...')
for i in range(1,101): # 
    ip[3] = str(i) # 
    ip_formatado = '.'.join(ip) #
    rs = os.system('ping -c 1 {}'.format(ip_formatado)) #
    if rs == 0:
        print ('O {} ta on'.format(ip_formatado))
  • 2

    Why Python? Could not be bash? Bash seems more suitable for the job

  • Doing the range from 1 to 101 starts to complicate in Bash. And this one may well be the beginning of a complete monitoring porgrma, etc...

2 answers

1

Like Jefferson Quesado commented, Bash is in fact the most appropriate tool for this task, and making the range is as simple as Python:

#!/usr/bin/env bash

for i in $(seq 1 101); do
    ip="192.168.1.${i}"
    status="$(ping -c 1 "${ip}" | grep "bytes from" && echo "on" || echo "off")"
    echo "${ip} ta ${status}"
done

0

os.system is a direct method, but the crudest of all to execute an external command: it executes the command, but does not give you any control over what the command prints, asks the user, etc...only returns whether there was error or not.

From the little bit of code that is there to understand that you want to be monitoring multiple addresses - using ping this way also makes the program wait for the success or failure of each ping - for its 101 addresses, this implies waiting a long time to run all.

The most sophisticated way to call an external process in Python is to use the "subprocess" module - it has several ways to open an external process - and we want one that: do not even show the output of the commands on the screen, and we can have more than one run at once. Since you are using "-c 1", this will not be necessary, but it is even possible for you to do this and keep monitoring each ping separately, from within Python when you have a more sophisticated program. For now, we can only pass a small timeout (1/20 seconds)- so that the return is almost immediate, and more than sufficient for a device on a local network to respond:

def principal(ip_base):
    componentes = ip_base.split(".")
    for rede in range(1, 101):
        ip = ".".join((componentes[0], componentes[1], str(rede), componentes[3]))
        try:
            resultado = subprocess.run(
                ["ping", "-c 1", ip,], 
                stdout=subprocess.DEVNULL,
                stderr=subprocess.DEVNULL,
                timeout=0.05
        )
        except subprocess.TimeoutExpired:
            continue
        if resultado.returncode == 0:
            print(f"O Ip {ip} está on")


if __name__ == "__main__":
    ip = input("Base de IP's para monitorar [192.168.0.1]: ")
    if not ip:
        ip = "192.168.0.1"
    principal(ip)

The call to subprocess.run includes the optional parameters for stdout, stderr and timeout: the first two to be "muted", and the maximum time to wait on timeout. If the timeout passes, it makes an exception - hence the try/except: as time spirals we move on to the next IP address. Check the documentation of the subprocess at: https://docs.python.org/3/library/subprocess.html

Note: the separation of your program into a function: never be too lazy to do this: it becomes much more readable, easy to change and expand the program, even if it could all be at the root of the module.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.