Более сложный способ мониторинга состояния сервера на Linux в реальном времени.

Продолжаю тему, начатую в предыдущей заметке [КОПИЯ]. В ней описывал получение данных от определенных скриптов и процессов запущенных на сервере под управлением Linux с помощью SSH, псевдотерминала и отдельного пользователя, создаваемого специально для целей мониторинга.

Будем посмотреть другой способ, с одной стороны, более сложный и требующий владения каким-нибудь языком программирования, кроме Bash-скриптов. Хотя, можно обойтись и исключительно одним Bash’ем, если клиент и сервер под Linux, или Bash прикрутили к Windows (cygwin(?), не пробовал, не знаю). А с другой стороны, наоборот, способ простой безопасный, требующий минимум вмешательства в настройки сервера.

На полноценный мануал не рассчитывайте, так, заметки на полях рабочего блокнота, чтоб не забыть и потом допилить под свои личные нужды.

Примечание: Термины «клиент» и «сервер» могут по ходу статьи быть неоднозначно истолкованными.
Серверное приложение будет наоборот, работать на «клиентском», «операторском» рабочем месте, а «сервер», в смысле компьютер с Linux, на котором я запускаю свои скрипты, и который управляет нужной мне железякой, станет вполне себе клиентом.
В общем, чтобы не вносить путаницы я условлюсь называть рабочее место оператора «локальным компьютером», а тот, который «сервер в привычном понимании» — «удаленным».

Задача

Такая же, как и в предыдущей заметке. Имеется удаленный компьютер под управлением Linux, рулящий системой контроля температуры и давления.
На самом деле, рулить он может чем угодно: от домашнего FTP с котиками или соединения с Интернетом, до управления СКД, открытием ворот, дверей, врат в Ад, личным концлагерем и т.д.
Суть в том, что нужно, чтобы удаленная система сигнализировала оператору об изменении своего состояния (изменении температуры, разрыва соединения с Интернетом, пришествии Сатаны). Оператор, как обычно, сидит под Windows (как в большинстве организаций в СНГ).

Некоторые соглашения

Для простоты условимся, что локальный и удаленный компьютер находятся в одной локальной сети (и одной подсети) 10.10.0.0/24, IP-адрес локального компьютера 10.10.0.30, прием данных производится через сетевой порт 11000 локального компьютера. Локальный и удаленный компьютеры обмениваются данными по протоколу TCP, данные представляют собой Unicode-строки.

Сервер приема сообщений на локальном компьютере

Для приема сообщений была создана программа-сервер, написанная на C# слушающая входящие сообщения на порту 11000 локального компьютера и выводящая их на консоль.

Никаких проверок, естественно, нет, использовать можно только для себя и работает оно идеально только в лабораторных условиях. Ссылка на весь код ниже. Кратко остановлюсь лишь на некоторых моментах:

//устанавливаем параметры сокета 
IPHostEntry ipHost = Dns.GetHostEntry("10.10.0.30");
IPAddress ipAddr = ipHost.AddressList[0];
IPEndPoint ipEndPoint = new IPEndPoint(ipAddr, 11000);

//создаем его
Socket sListener = new Socket(ipAddr.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
...
//слушаем входящие соединения
sListener.Bind(ipEndPoint);
sListener.Listen(10);
while (true) //НИКОГДА не делайте так в реальных программах
                {
                    Console.WriteLine("Ожидаем соединение через порт {0}", ipEndPoint.Port);
                    Console.WriteLine("Локальный адрес {0}", ipEndPoint.Address);
 
                    // Программа приостанавливается, ожидая входящее соединение
                    Socket handler = sListener.Accept();                    
                    string data = null;
 
                    // Мы дождались клиента, пытающегося с нами соединиться
 
                    byte[] bytes = new byte[1024];
		    
                    Console.WriteLine("Сообщение получено, ожидаем данные (5 с)");
                    Thread.Sleep(5000); //НИКОГДА так не делайте, чтобы 
		//не потерять входящие данные, используйте асинхронные методы, например
		//и разработайте свой протокол высокого уровня с маркерами конца сообщения
		//подтверждениями приема данных и прочими нужными вещами!!!
...


Смотреть весь код
Скачать с Mega.nz
Основано на коде из статьи

Скрипт для отправки сообщений на удаленном компьютере.

Bash, как оказывается, имеет возможность обмениваться сообщениями по локальной сети, а точнее, записывать и считывать нужные данные в порт на компьютер с определенным адресом (как IP, так и поименованном). Для ознакомления со всеми возможностями, настоятельно рекомендую обратиться к разделу источников в конце заметки. Здесь же я опять, остановлюсь только на основных командах.

Открытие TCP/UDP сокета средствами Bash

#!/bin/bash

echo "Open"
exec 3>/dev/tcp/10.10.0.30/11000

Ключевая команда здесь exec. С ее помощью открываем нужный сокет, тем самым соединяясь с необходимым компьютером на определенном порту.

где:
3 — Файловый дескриптор. Дескрипторы 0, 1 и 2 зарезервированы, соответственно за устройствами stdin, stdout и stderr. Для своих нужд можно использовать дескрипторы, начиная с 3, в стандартных случаях они никем не используются, а нестандартные я позволю себе опустить.
tcp — указание на протокол (точнее, на виртуальное устройство, ассоциируемое с этим протоколом). Обычно принимает значения tcp или udp.
> — указание, что сокет открыт для записи. Возможны варианты < — для чтения. <> — для чтения и записи.
10.10.0.30 — IP (или URL) компьютера, которому посылаем (принимаем) сообщения.
11000 — номер порта.

Примечание: Порт должен быть открыт в файерволе на локальном и удаленном компьютере.
Примечание: Для получения возможности открытия сокетов средствами командной оболочки bash необходима активация механизма поддержки виртуальных файлов устройств сокетов на этапе сборки бинарного файла этой командной оболочки из исходных кодов (т.е., его сборки с активацией возможности «—enable-net-redirections»). В устаревших версиях дистрибутивов данная возможность bash может быть деактивирована, причем в этом случае вы будете получать следующее сообщение об ошибке после каждой попытки открытия сокета:

/dev/tcp/xmodulo.com/80: No such file or directory

Помимо командной оболочки bash, виртуальные устройства сокетов поддерживаются такими командными оболочками, как ksh и zsh.[2]

Отправка сообщения

Отправить сообщение в открытый сокет можно с помощью команды echo:

echo -e $1 >&3

Закрытие сокета

В данном примере, после отправки каждого сообщения, сокет нужно закрывать, освобождая дескриптор файла. Возможно, это можно как-то побороть и держать сокет открытым постоянно, но у меня не сработало.

exec 3>&-

где:
3 — вышеупомянутый дескриптор файла
> — должно принимать соответствующие значения для открытого на запись (>), чтение (<) или двунаправленного сокета (<>). Двунаправленный сокет должно быть можно превратить в однонаправленный, если это вдруг понадобится.
&- — указание на закрытие соответствующего сокета.

Код

Сервера приема сообщений:
Смотреть на PasteBin
Скачать с Mega.nz

Скрипта отправки сообщений:
Смотреть на PasteBin
Скачать с Mega.nz

Источники

1. Клиент-серверное приложение на потоковом сокете TCP [Копия]
2. Как открыть TCP-/UDP-сокет средствами командной оболочки bash [Копия]

Видеоиллюстрация

Прямая ссылка

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *