Частенько возникает необходимость поадминить удаленную юзерскую машину, которая в данный момент выключена. Раньше приходилось просто время от времени пинговать, чтобы отследить, когда машина появится в сети. Сейчас написал не шибко большой скрипт, выполняющий эту работу за меня. Скрипт написан на Perl и использует sqlite и libnotify. Сам скрипт и пример использования под катом.
Итак, сам скрипт:
#!/usr/bin/perl use strict; use subs; use DBI; use Net::Ping::External qw(ping); sub dbinit { my $home = $ENV{HOME}; my $db = DBI->connect("dbi:SQLite:dbname=".$home."/.ipnotify.db","",""); my $iqry = $db->do("create table if not exists hosts(hostname TEXT)"); $db->disconnect(); } sub add { my $home = $ENV{HOME}; my $db = DBI->connect("dbi:SQLite:dbname=".$home."/.ipnotify.db","",""); if ($_[0] eq "") { printf "expected hostname\n"; } else { my $qry = $db->do("insert into hosts values ('".$_[0]."')"); printf $qry." hosts added to monitor list\n"; } $db->disconnect(); } sub del { my $home = $ENV{HOME}; my $db = DBI->connect("dbi:SQLite:dbname=".$home."/.ipnotify.db","",""); if ($_[0] eq "") { printf "expected hostname\n"; } else { my $qry = $db->do("delete from hosts where hostname ='".$_[0]."'"); if ($qry == 0) { printf "no such entry\n"; } else { printf "ok\n"; } } $db->disconnect(); } sub list { my $home = $ENV{HOME}; my $db = DBI->connect("dbi:SQLite:dbname=".$home."/.ipnotify.db","",""); my $qry = $db->prepare("select hostname from hosts order by hostname"); $qry->execute() or die("db query failed: ".$db->errstr); my$cnt = 0; while ((my $hostname) = $qry->fetchrow_array()) { printf $hostname."\n"; $cnt++; } if ($cnt == 0) { printf "no entries\n"; } $qry->finish(); undef $qry; $db->disconnect(); } sub daemon { my %states = (); while (1 == 1) { my $home = $ENV{HOME}; my $db = DBI->connect("dbi:SQLite:dbname=".$home."/.ipnotify.db","",""); my $qry = $db->prepare("select hostname from hosts"); if ($qry->execute()) { while ((my $host) = $qry->fetchrow_array()) { my $notify = 0; if (ping(hostname => $host, timeout => 1)) { unless (exists($states{$host})) { $states{$host} = 1; $notify = 1; } else { if ($states{$host} == 0) { $states{$host} = 1; $notify = 1; } } } else { $states{$host} = 0; } if ($notify == 1) { `notify-send -u normal IPNotify "$host is online!"`; } } } $qry->finish(); undef $qry; $db->disconnect(); } } dbinit(); if (($ARGV[0] eq "") || (($ARGV[0] ne "add") && ($ARGV[0] ne "del") && ($ARGV[0] ne "list") && ($ARGV[0] ne "daemon"))) { printf "IPNotify usage:\n"; printf "ipnotify daemon | list | add <host> | del <host>\n"; } else { if ($ARGV[0] eq "list") { list(); }; if ($ARGV[0] eq "daemon") { daemon(); }; if ($ARGV[0] eq "add") { add($ARGV[1]); }; if ($ARGV[0] eq "del") { del($ARGV[1]); }; }
И как это использовать.
$ ipnotify IPNotify usage: ipnotify daemon | list | add <host> | del <host>
Все просто – четыре команды: запуск демона, показ списка отслеживаемых хостов, добавление хоста в список, удаление хоста из списка. Прежде всего надо запустить демона в фоне командой:
$ ipnotify daemon
Демон запущен и готов обслуживать своего пользователя.
$ ipnotify list no entries
Сейчас список пуст. Добавим в него хост.
$ ipnotify add infomrk 1 hosts added to monitor list
Через некоторое время демон проверит хост на живость и покажет уведомление:
Интервал опроса хостов на живость – 60 секунд. Если отпала необходимость мониторинга хоста, его можно удалить из списка:
$ ipnotify del infomrk ok
При желании, любой более-менее разбирающийся в программировании сможет поправить исходник под себя: поправить таймауты и интервалы, изменить способ уведомления и т.д.
Февраль 14, 2010 в 05:56
А Wake On Lan чего не используешь?
Февраль 14, 2010 в 08:35
Дак это ж воде немного другое, если я не путаю. Wake on LAN вроде как позволяет удаленно пробудить систему от спячки специальным пакетом. Разве не так?
Июль 19, 2010 в 05:06
Ну да, только не только пробудить, но и в включить (если она в розетку включена конечно).
Включил машину WakeOnLan’ом и админи ее на здоровье.