Using subprocess.run caused script to hang

56 Views Asked by At

First time asking a question here.

So I have been task to create a script that checks if a device is reachable via ping. Just liek to point out that I was able to create a working script on my laptop and was able to get our desired output. My laptop runs Python 3.11.4.

Now, we need to run all of our script in our scripting server(required by company policy). We have a dedicated scripting server. We mostly run our network automation in that linux scripting server. It uses python 3.7.5.

The issue is that, when I run the same script in the Linux scripting server, it hangs. No echo or whatsoever. Needed to press "CTRL+C" to stop it. When I did, it will return the below information:

**^CTraceback (most recent call last):
  File "ping_nodes.py", line 28, in <module>
    shell=False)
  File "/usr/lib/python3.7/subprocess.py", line 490, in run
    stdout, stderr = process.communicate(input, timeout=timeout)
  File "/usr/lib/python3.7/subprocess.py", line 951, in communicate
    stdout = self.stdout.read()**

After line-by-line isolation, the part where it actually hangs is the subprocess.run part, given below, where IP is a variable that contains our IP Addresses. I tried only using one IP Address but still the same behavior.

pingcheck = subprocess.run(["ping", "-n", "5", ip], stdout = subprocess.PIPE, stderr = subprocess.STDOUT)

When I add "Shell=True" it actually doesn't hang, BUT the result is different than what we want to see.

Is this something about the different python versions? Please if anyone our here has an idea, I'm open to anything.

Thank you! -Newbie programmer

Tried adding a timeout=50 parameter, but it just showed an error "Command '['ping', '-n', '5', '8.8.4.4']' timed out after 50 seconds". But when I run it on my laptop, with or without the timeout paramaters, it worked flawlesly.

Isolated the part of the script where it hangs is in the subprocess.run part. No echo, need keyboardInterrupt to stop.

Tried adding Shell=True, and the she script didn't hang. Weird... But the result we are parsing are different if the Shell is set to true. We prefer it to ba False.

1

There are 1 best solutions below

0
SIGHUP On

As I understand your problem, all you're trying to achieve is determine if a given host can be ping'ed. If that's the case then:

from subprocess import run, DEVNULL, CalledProcessError
from platform import system

# if timeout is given it should be in seconds.
# it will be converted to milliseconds for Windows
def can_ping(host: str, count: int=5, timeout=None|int) -> bool:
    if system() == "Windows":
        c = "/n"
        t = "/w"
        m = 1_000
    else:
        c = "-c"
        t = "-t"
        m = 1
    args = [
        "ping",
        c,
        str(count)
    ]
    if timeout is not None and isinstance(timeout, int):
        args.extend([t, f"{timeout*m}"])
    args.append(host)

    try:
        run(args, stdout=DEVNULL, stderr=DEVNULL, check=True)
    except CalledProcessError:
        return False
    return True


print(can_ping("www.nonsense.corp", timeout=1))
print(can_ping("www.google.com"))

Output:

False
True