LINUX.ORG.RU

Python следить за состоянием порта.

 , ,


0

2

День добрый всем!

Пытаюсь встать на путь истинный, нужен код который бы слушал определенный порт и если порт умер, делал какое-то действие. Пришел к такому виду:

#!/usr/bin/python3.5

import socket;
import threading;

def CUSTOMPORT():
        threading.Timer(1.0, CUSTOMPORT).start()
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        result = sock.connect_ex(("192.168.1.10",80))
        if result == 0:
                print ("Run")
        else:
                print ("Down")

CUSTOMPORT()

Все как бы хорошо, запускаю Nginx все отрабатывает. Но не пойму никак как мне НЕ циклично получать ответ? Например, что бы если я запустил сервер, то программа вернула бы мне только одно значение - Down, но продолжала слушать. А если сервер вернулся, скала что Run.

Пробовал по sys.exit(), но это завершает совсем. Нужен некий wacth-чер. Пните в нужном направлении. Спасибо!


эм, например хранить предыдущее сосотояние и писать если оно изменилось ?

Dred ★★★★★
()
Ответ на: комментарий от Dred

Вот как раз над этим, я как бы и ломаю голову! :)

yakunin
() автор топика

Если в ассинхронщину:

import asyncio


class CheckProtocol(asyncio.Protocol):
    def __init__(self, loop):
        self.loop = loop

    def connection_made(self, transport):
        print('Open connection')

    def connection_lost(self, exc):
        print('Close connection')


async def connection():
    while True:
        try:
            transport, protocol = await loop.create_connection(
                lambda: CheckProtocol(loop), '127.0.0.1', 3000)
            transport.close()
        except ConnectionRefusedError:
            print('Connection refused')

        await asyncio.sleep(1.0)


async def check_port():
    await asyncio.wait([connection()])


loop = asyncio.get_event_loop()
loop.run_until_complete(check_port())
loop.close()

...
Open connection     # порт доступен
Close connection
Open connection
Close connection
connection refused  # порт недоступен
connection refused
connection refused
connection refused
connection refused
connection refused
Open connection     # порт доступен
Close connection
Open connection
Close connection
...

Раз в секунду коннектимся к порту и тут же отключаемся, если коннект не идёт, то ловим эксепшн.

vvn_black ★★★★★
()
Ответ на: комментарий от vvn_black

В этом и суть, суть в том, что я хочу получить не постоянный вывод, а только одну строку тогда, когда статус меняется. Мой код прекрасно работает, но он отдает как раз так:

У меня сервер выключен, запускаю ватчер, идет вывод каждую секунду что он выключен, я запустил его, каждую секунду пошло что он в сети, дальше опять выключил, получил каждую секунду off.

Server is off
Server is off
Server is off
Server is off
Server is off
Server is on
Server is on
Server is on
Server is off
Server is off
Server is off
Server is off

А мне нужно вывод только при смене статуса, то есть должно было быть:

Server is off
Server is on
Server is off
yakunin
() автор топика
Ответ на: комментарий от yakunin

Теперь понятно, а в чём именно проблема, вот как пример:

class Clicker(object):
    prev_button = None

    def click(self, button=None):
        if button != self.prev_button:
            self.prev_button = button
            print(button)

...
clc = Clicker()

...
# Меняем принты
clc.click(button='Server is on')

...
clc.click(button='Server is off')
vvn_black ★★★★★
()
Последнее исправление: vvn_black (всего исправлений: 1)
Ответ на: комментарий от vvn_black

Я пока не освоил классы в Python, понимаю что вы в данном примере наследуете класс и потом этот класс обрабатываете. А на моей задаче не могли бы показать пример? Я так и не понял как это реализовать.

yakunin
() автор топика
Ответ на: комментарий от yakunin
#!/usr/bin/python3.5

import socket;
import threading;


class Clicker(object):
    prev_button = None

    def click(self, button=None):
        if button != self.prev_button:
            self.prev_button = button
            print(button)


def CUSTOMPORT():
    threading.Timer(1.0, CUSTOMPORT).start()
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        result = sock.connect_ex(("192.168.1.10",80))
        if result == 0:
            clc.click("Run")
        else:
            clc.click("Down")

clc = Clicker()
CUSTOMPORT()
vvn_black ★★★★★
()
Последнее исправление: vvn_black (всего исправлений: 1)
Ответ на: комментарий от vvn_black

ебать нелья было дать человеку простое решение чтоб он смысл понял а не свое ООП головного мозга демонстрировать? фу так писать и пистон такого вообще не поощряет, вот в чем смысл:

state = None # хранилище предыдущего значения переменной состояния
loop: # твой цикл, например while True:
  value = get_value ... # получение текущего состояния порта (просто любое значение)
  if value is not state: # если текущее состояние отличается от предыдущего
    fire_event({"state": {"previous": state, "next": value}}) # вызов события оповещения об изменившемся состоянии сервера (напеример, было up а стало down, смотря что вернет твоя функция проверки
    # в простом случае
    print(f"Состояние сервера изменилось с {state} на {value}")
    # теперь самое главное, сохранение текущего состояния как предыдущего, для сравнении в следующем шаге цикла и лучше это делать до предыдущих вызовов на случай исключения в них
    state = value
anonymous
()
Ответ на: комментарий от anonymous

чтоб он смысл понял

От ты хорош критиковать, во-первых ТС никак свой уровень не обозначил, во-вторых так запутал очень хорошо, начал с порта и сокетов, а в итоге ему какой-то глобальный стейт оказался нужен.

а не свое ООП головного мозга демонстрировать

Ага так всё и начинается с глобальных переменных, потом доходит до goto и т.п.

Представь, если состояние порта в 10 разных местах меняется, что 10 раз портянку из кондишенов вставлять? Не проще сразу логгер/принт переопределить?

vvn_black ★★★★★
()
Последнее исправление: vvn_black (всего исправлений: 2)
Ответ на: комментарий от vvn_black

Спасибо, Вы мне помогли. Да, я уровень не обозначил, факт. Но думаю что можно сделать и проще, наверное.

Что требовалось. Требовалось следить за сокетом удаленной машины, например там запущен nginx. Если сокет отвечает, значит выводим сообщение что Server is run и опрашиваем его каждую секунду, если вдруг сервис пожух, говорим Server is down и предпринимаем какое-то другое действие, например поднимаем nginx на том сервере с которого слушаем.

Некий watch-чер, если так можно сказать. Это я пытаюсь реализовать. Единственное в чем меня берут сомнения, не будет ли это похоже на DDoS или что-то в этом духе. :) Но вам спасибо в любом случае вы дали рабочий вариант, а позже попробую разобраться что там и как в этом классе и процедуре.

yakunin
() автор топика
Ответ на: комментарий от vvn_black

В общем, поняв конструкцию, я пришел к такому варианту:

#!/usr/bin/python3.4

import socket
import threading

myvar = None

def CUSTOMPORT():
        global myvar
        threading.Timer(0.5, CUSTOMPORT).start()
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        result = sock.connect_ex(("192.168.1.10",80))

        if myvar != result:
                if result == 0:
                        print ("Service is up")
                else:
                        print ("Service is down")
        myvar = result

CUSTOMPORT()

Это проще и без наследования классов. Спасибо ещё раз! Теперь все работает как надо.

yakunin
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.