Код выдаёт ложный успешный ping

Странная проблема: Код, который дважды проверяет пинг, после чего перезагружает компьютер работает только если изначально был интернет или появился в процессе но потом упал. Если при включении нет интернета то он считает пинг успешным. (Также код добавляет себя в автозагрузку, для удобной перезагрузки сервера)

import time
import datetime
import platform
import os
import subprocess
import getpass
import sys
USER_NAME = getpass.getuser()


ping_problem = 0


def add_to_startup():
    file_path = get_full_script_name()  # Путь к файлу скрипту
    bat_path = r'C:\Users\%s\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup' % USER_NAME
    with open(bat_path + '\\' + "ReloadForServer.bat", "w+") as bat_file:
        bat_file.write(r'start "" "%s"' % file_path)


add_to_startup()


def ping(host):
    parameter = '-n' if platform.system().lower() == 'windows' else '-c'
    command = ['ping', parameter, '1', host]
    return subprocess.run(command, stdout=subprocess.PIPE).returncode == 0


while ping_problem != 2:
    host = "google.com"
    ping(host)
    if ping(host):
        print("Ping is successful :)")
        ping_problem = 0
        time.sleep(120)
    else:
        print(":(")
        current_time = datetime.datetime.now().time()
        print(current_time, 'Ping has been failed')
        ping_problem += 1
    time.sleep(120)

print('Ошибка! Лимит попыток восстановления соединения был исчерпан'
      'Начинаю перезагрузку системы')
os.system('shutdown /r /t 0')

p.s всё это дело на Windows 10 P.p.s Иные предложения по улучшению кода приветствуются, я новичок


Ответы (1 шт):

Автор решения: Савельев Даниил

Если командная строка на английском, то оно не сработает, нужно менять параметры для отсеивания (для мультифункциональности можно переделать, используя библиотеку icmplib

Код вылавливает слова с информацией об ошибке и отправляет False, если есть.

Это основная часть кода:

def ping():
    try:
        # Выполнение пинга
        parameter = subprocess.run(  # Получение результата
            ["ping", "-n", config["Main_Data"]["files_send"], config["Main_Data"]["host"]],
            shell=True,
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE,
        )  # не рекомендую ставить автоматическую декодировку через text = True
        output = parameter.stdout.decode('866')  # не на Windows может понадобиться другой номер
        print(output)
        if "Общий сбой." in output \
                or "Превышен интервал ожидания для запроса." in output \
                or "Заданный узел недоступен." in output:  # Проверка на наличие сообщений об ошибках
            return False
        return True
    except Exception as error:  # если всё полностью поломалось
        print(f"Ошибка при выполнении ping: {error}")
        return False

Также был изменён код для батника, если надо:

def get_full_script_name():  # получаем путь файла + имя файла с расширением
    route_path = Path(sys.argv[0])
    return route_path.resolve()


def add_to_startup():
    file_path = get_full_script_name()  # Путь к файлу скрипту
    bat_path = r'C:\Users\%s\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup' % USER_NAME
    with open(bat_path + '\\' + "ReloadForServer.bat", "w+") as bat_file:
        bat_file.write(r'start "" "%s"' % file_path)

Для пластичности программы был добавлен ini-файл:

# settings.ini
[Main_Data]
timesup = 60
first_ping = 20
host = 8.8.8.8
files_send = 4
errors_in_a_row = 2
timer_is_visible = True

Полный код программы на данный момент:

import os
import time
from datetime import datetime
import subprocess
import getpass
import sys
from pathlib import Path
import configparser

USER_NAME = getpass.getuser()  # парсим имя пользователя

config = configparser.ConfigParser()  # парсим инишник
config.read("settings.ini")  # данные в ini файле для гибкости программы


def timer(first):  # ожидание между пингами
    timers_time = 0
    target_time = int(config["Main_Data"]["first_ping"]) if first else int(config["Main_Data"]["timesup"])
    while timers_time < target_time:
        timers_time += 1
        time.sleep(1)
        if config["Main_Data"]["timer_is_visible"] == 'True':  # опциональный отсчёт
            print(timers_time)
    print('Ping...')


def get_script_name():  # получаем имя файла с расширением
    script_path = Path(sys.argv[0])
    return script_path.name


def get_full_script_name():  # получаем путь файла + имя файла с расширением
    route_path = Path(sys.argv[0])
    return route_path.resolve()


def add_to_startup():
    file_path = get_full_script_name()  # Путь к файлу скрипту
    bat_path = r'C:\Users\%s\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup' % USER_NAME
    with open(bat_path + '\\' + "ReloadForServer.bat", "w+") as bat_file:
        bat_file.write(r'start "" "%s"' % file_path)


add_to_startup()


def ping():
    try:
        # Выполнение пинга
        parameter = subprocess.run(  # Получение результата
            ["ping", "-n", config["Main_Data"]["files_send"], config["Main_Data"]["host"]],
            shell=True,
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE,
        )  # не рекомендую ставить автоматическую декодировку через text = True
        output = parameter.stdout.decode('866')  # не на Windows может понадобиться другой номер
        print(output)
        if "Общий сбой." in output \
                or "Превышен интервал ожидания для запроса." in output \
                or "Заданный узел недоступен." in output:  # Проверка на наличие сообщений об ошибках
            return False
        return True
    except Exception as error:  # если всё полностью поломалось
        print(f"Ошибка при выполнении ping: {error}")
        return False


# выводим информацию о конфигурациях
print(get_script_name(), 'запущен')
print('Ping\'s host', config["Main_Data"]["host"])
print("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@")
print('Частота ожидания между каждым пингом на', config["Main_Data"]
     ["host"], '-', config["Main_Data"]["timesup"], 'секунд')
print("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@")
print('Первичный пинг', config["Main_Data"]["first_ping"], 'секунд')
timer(True)

# Проверка наличия интернета сразу при запуске, чтобы не тратить время
if not ping():
    print("Ошибка! Интернет недоступен при запуске")
    print('Начинаю перезагрузку системы')
    os.system('shutdown /r /t 0')
print("Первичный пинг успешен :)")
ping_problem = 0

while ping_problem < int(config["Main_Data"]["errors_in_a_row"]):  # общее выполнение программы
    timer(False)
    if ping():
        print("Пинг успешен :)")
        ping_problem = 0
    else:
        print(":(")
        print('Ошибка пинга')
        ping_problem += 1
    now = datetime.now()
    time_info = now.strftime("%d/%m/%Y %H:%M:%S")  # настройка локального времени
    print(time_info)

print('Ошибка! Лимит попыток восстановления соединения был исчерпан. Начинаю перезагрузку системы')
os.system('shutdown /r /t 0')

P.S. За информацию спасибо @mrgervant. Я позже, возможно, прикреплю код через icmplib.

→ Ссылка