Как стать автором
Обновить

Скрипт для мониторинга состояния хостов в сети

Время на прочтение3 мин
Количество просмотров5.8K
Я работаю админом и в моей зоне ответственности находится ряд серверов: роутеры, серверы БД, терминальные серверы и т.д. И хочется быть в курсе, если какойто из серверов вдруг пропал из сети — где-то упал линк с удаленной сетью, где-то вдруг произошел хрестоматийный случай с техничкой, шваброй и кабелем, где-то еще какой форс-мажор случился. И при этом не хочется заморачиваться с тяжеловесными системами мониторинга, вроде Zabbix.

Хочу поделиться с обществом своим скриптом для своевременного уведомления о пропавшей связи с серверами. Скрипт написан на Perl и крутится на моем рабочем десктопе в среде Debian GNU/Linux. Скорей всего без лишних приседаний запустится и в другом дистрибутиве линукса.
Итак, скрипт с комментариями:
#!/usr/bin/perl

# Подключаем модули: 
use strict; # Включаем строгое определение переменных.
use Net::Ping::External qw(ping); # Подключаем модуль для ICMP-пинга

# Конфигурационные переменные:
my $tries = 3; # Количество попыток пинга каждого хоста
my $timeout = 5; # Таймаут пинга
my $interval = 5; # Интервал между проверками

# Хеш-массив с хостами для проверки. Имя для отображения => айпи или хостнейм
my %hosts = (
	"HOST-1" 	=> "10.0.0.1",
	"HOST-2" 	=> "10.0.0.2"
);

# Далее, собственно, сам скрипт

# Определеяем вспомогательный хеш, в котором  будут храниться состояния хостов
my %state = ();

# По умолчанию все хосты живые
while (my ($name, $ip) = each(%hosts)) {
	$state{$name} = "UP";
}

# Запускаем бесконечный цикл
while () {
        # Массивы для вновь упавших и вновь поднявшихся хостов
	my @uphosts = ();
	my @downhosts = ();

        # Проходим в цикле весь хеш проверяемых хостов
	while (my ($name, $ip) = each(%hosts)) {

                # Счетчик ответов сбрасываем в ноль
		my $cnt = 0;

                # Выполняем нужное количество пингов, увеличивая счетчик ответов при удачных пингах
		for (my $i = 1; $i <= $tries; $i++) {
			if (ping(hostname => $ip, timeout => $timeout)) {
				$cnt++;
			}
		}
                # Если хост не ответил ни разу, он предположительно мертв
		if ($cnt == 0) {

                       # Если до этого он был жив, надо уведомить админа о вновь упавшем хосте, добавляем в список
			if ($state{$name} eq "UP") {
				$state{$name} = "DOWN";
				push(@downhosts, $name);
			}
                # Если хост ответил хоть на один пинг - он жив
		} else {

                        # Снова проверяем предыдущее состояние
			if ($state{$name} eq "DOWN") {
				$state{$name} = "UP";
				push(@uphosts, $name);
			}
		}
	}

       # Поверки закончены, проверяем списки и, если есть хосты с изменившимися состояниями, 
       # уведомляем админа средствами libnotify
	if (scalar(@uphosts) > 0) {
		my $lst = join(", ", @uphosts);
		`notify-send -u normal NetMon "Hosts becomes up: $lst"`;
	}
	if (scalar(@downhosts) > 0) {
                my $lst = join(", ", @downhosts);
                `notify-send -u critical NetMon "Hosts becomes down: $lst"`;
        }
	
       # Отдыхаем заданный интервал времени
	sleep($interval * 60);
};


Теперь оговорки по скрипту.
У перла, а конкретно у Net:Ping есть особенность. Если использовать встроенный перловый модуль Net::Ping с типом пинга ICMP, то потребуются привилегии суперпользователя root. Это связано с реализацией ICMP-пинга в этом модуле через RAW-сокеты, которыми имеет право пользоваться только root. Поэтому я использовал в этом скрипте Net::Ping::External, который реализует пинг через внешние вызовы.
Помимо уведомления админа всплывающими нотифами можно дописать, например, запись информации о падениях-поднятиях в текстовый лог (свой или через syslog), можно отправлять сообщения на мыло, в джаббер, смс на телефон и т.д. Полный полет для фантазии.
До кучи, можно дописать проверку на живость сервисов, например веб, почты, фтп, самбы. Но это уже выйдет за рамки простого пинговальщика и будет похоже на тяжеловесные системы мониторинга.
Теги:
Хабы:
Всего голосов 5: ↑4 и ↓1+3
Комментарии14

Публикации