Search     or:     and:
 LINUX 
 Language 
 Kernel 
 Package 
 Book 
 Test 
 OS 
 Forum 
iakovlev.org

Automating UNIX and Linux Administration by Kirk Bauer

Chapter 10 : System Monitoring
 Скрипты для этой книги лежат тут (40 кб)
 
  Для администратора мониторинг компьютеров в сети должен быть построен так , 
 чтобы он мог получать отчет о неисправностях не только после их возникновения , 
 но и мог бы предотвращать их появление.
 Мониторинг можно разделить на 3 основных части :
   1. Проверка системы на уровне железа - доступное дисковое пространство , 
         неполадки в работе драйверов и т.д.
   2. Проверка логов на предмет аномалий.
   3. Проверка сервисов .
 
   

Система отчетов

Следующий перловый скрипт имеет 2 командных аргумента . Первый - уровень значимости (WARNING или CRITICAL), второй собственно само сообщение ("disk failure"). Аргумент под названием stdin может включать многострочный отчет . Начало скрипта будет таким : #!/usr/bin/perl -w use strict; # Configuration items my $MailThreshold = 'WARNING'; my $LogFile = '/var/log/event.log'; my $Email = 'alert@company.com'; # Available log levels my %Levels = ( 'INFO' => 1, 'WARNING' => 2, 'ERROR' => 3, 'CRITICAL' => 4 ); sub usage () { print STDERR "Usage: $0 [--stdin] \n"; print STDERR "Levels: "; foreach (keys %Levels) { print STDERR "$_ "; } print STDERR "\n"; exit 1; } Письмо будет отправлено по адресу $Email , при этом отчет ляжет в $LogFile. Следующая часть скрипта проверяет аргументы,проверяет имя хоста: # Check and store parameters my $stdin = 0; if ($ARGV[0] eq '--stdin') { shift @ARGV; $stdin = 1; } usage() unless ($#ARGV == 1); usage() if ($ARGV[0] eq '--help'); my ($level, $subject) = @ARGV; $level = uc($level); usage() unless ($Levels{$level}); # Determine system's hostname (first portion only) my $hostname = 'hostname'; chomp($hostname); $hostname =~ s/\..*$//; # Store formatted date string my $date = localtime; Следующая часть скрипта сработает при условии , что внешний аргумент –stdin пустой : open (LOG, ">>$LogFile"); unless ($stdin) { if ($Levels{$level} >= $Levels{$MailThreshold}) { system ("mail -s '[$level] $hostname: $subject' '$Email'"); } print LOG "$date $hostname [$level] $subject"; close(LOG); exit 0; } Следующая часть скрипта сработает при условии , что внешний аргумент –stdin непустой : Каждая строка stdin будет добавлена к логу . При этом они сохраняются в массиве. my @lines; while (my $line = ) { push @lines, $line; print LOG "$date $hostname [$level] $subject: $line"; } close(LOG); if ((@lines) and $Levels{$level} >= $Levels{$MailThreshold}) { open (MAIL, "| mail -s '[$level] $hostname: $subject' '$Email'"); foreach (@lines) { print MAIL $_; } close(MAIL); } exit 0; Использовать этот скрипт можно по-разному . например , usr/local/sbin/report INFO 'Test report' < /dev/null В следующем примере в лог уйдет доступное дисковое пространство : df | /usr/local/sbin/report --stdin INFO 'Available drive space' Если мы хотим допустим проверить загрузку системы , мы набираем команду : uptime 10:18am up 1:16, 1 user, load average: 0.29, 0.20, 0.18 Если мы хотим , чтобы при критических значениях сообщение о перегрузке поступало в лог , можно с помощью крона запускать с определенной периодичностью такую команду : uptime | awk '{if ($10 > 1.00) print "15-min average: " $10}' | \ /usr/local/sbin/report --stdin WARNING 'High Load Average' Следующий шелловский скрипт проверяет доступное дисковое пространство для файловых систем , определенных в переменной $types : #!/bin/bash types="ext2|ext3|ufs|vfat" cutoff="90" for drive in 'mount | awk "/type ($types)/ {print \\\$1}"' ; do df "$drive" | awk -v "cutoff=$cutoff" '/^\// { gsub(/%$/, "", $5); if ($5 > cutoff) print "Drive " $1 " (" $6 ") is " $5 "% Full" }' done | /usr/local/sbin/report --stdin WARNING 'Drives almost full' Рассмотрим подробнее работу этого скрипта . Во-первых, командой mount мы определяем доступные партиции . Затем для каждой партиции запускается команда df . С помощью команды awk мы обрабатываем вывод Мы передаем для awk аргумент cutoff . awk будет обрабатывать только те строки , которые начинаются со слэша . Функция gsub используется для удаления символа процента в 5-м столбце для того , чтобы извлечь число , которое сравнивается с cutoff . Если число болше , чем cutoff , для данной партиции генерится output . Кроном такой скрипт может запускаться раз в день . В каждой системе есть сервисы-демоны , которые работают постоянно . Для удаленного доступа это сервис sshd . Также это могут быть mail, DNS, web server. Проверка сервиса sshd : ps ax -o '%c %P' | grep 'sshd' sshd 1 sshd 12599 sshd 12599 sshd 12599 sshd 12599 sshd 12599 sshd 12599 sshd_checker 1 Мы видим , что во 2-м столбце выводятся id-шники как родительского , так и дочерних процессов . нам интересен только родительский : ps ax -o '%c %P' | grep 'sshd' | grep '1$' sshd 1 sshd_checker 1 отфильтруем до нужной кондиции % ps ax -o '%c %P' | awk '{if (($2 == 1) && ($1 == "sshd")) print $0}' sshd 1 Для проверки удаленного демона можно запустить скрипт на веб-сервере . Следующий скрипт проверяет URL каждые 30 секунд , при этом для HTTP-запроса используется wget : #!/bin/bash SLEEP=30 #seconds TIMEOUT=10 #seconds URL='http://localhost/index.html' MATCH='' while true ; do wget -q -O - -T=$TIMEOUT --tries=1 "$URL" | grep -q "$MATCH" || { /usr/local/sbin/report ERROR "Web server not responding" /etc/rc.d/init.d/httpd restart && { /usr/local/sbin/report INFO "Web server restarted" } } sleep $SLEEP done Следующий скрипт запускает команду rpm -qa , которая проверяет список установленных пакетов , сравнивает с предыдущим списком . Команда sed обрабатывает output . !/bin/bash TMPDIR="$HOME/tmp" rpm -qa | sort > $TMPDIR/packages.curr if [ -r $TMPDIR/packages.last ] ; then diff $TMPDIR/packages.last $TMPDIR/packages.curr | \ sed -n -e 's/^/Added/p' | \ /usr/local/sbin/report --stdin INFO 'Packages changed' fi mv $TMPDIR/packages.curr $TMPDIR/packages.last

Monitoring Network Services

Простейшая форма проверки сети - пинг . Но пинг ничего нам не скажет о состоянии удаленной системы , если даже она отвечает . Следующая форма мониторинга - проверка портов . Коннект на 80-й порт говорит о том , что по крайней мере на машине работает веб-сервер . Рассмотрим пример скрипта , который проверяет демона . Запустим команду , которая проверяет список запущенных процессов : ps ax PID TTY STAT TIME COMMAND 1 ? S 1:46 init 20288 ? S 0:06 /usr/sbin/httpd -DHAVE_PROXY... Обработаем вывод этой команды в скрипте : #!/bin/bash process="/usr/sbin/httpd" start="service httpd restart" ps ax | awk '{print $5}' | grep -q "^$process$" || { # Apparently not running, so start the process eval "$start" exit $? } exit 0 Скрипт имеет 2 переменных - имя проверяемого демона (httpd) и команда , которая запускается в случае , если проверяемый демон не запущен . Следующий скрипт проверяет порт . Для начала запустим команду : netstat -ln Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN tcp 0 0 0.0.0.0:6000 0.0.0.0:* LISTEN ... Преобразуем вывод : netstat -ln | awk '/^tcp/ {print $4}' 0.0.0.0:80 0.0.0.0:6000 0.0.0.0:22 Теперь скрипт : #!/bin/bash port="80" restart="service httpd restart" netstat -ln | awk '/^tcp/ {print $4}' | grep -q ":$port$" || { # Apparently not listening, so run restart command eval "$restart" exit $? } exit 0 В следующем скрипте делается запрос на удаленный URL и проверяется веб-сервис : #!/bin/bash URL="http://localhost/netsaint/index.html" TIMEOUT=10 #(seconds) MATCH="" restart="service httpd restart" wget -q -O - -T=$TIMEOUT --tries=1 "$URL" | grep -q "$MATCH" || { # Something is wrong, so restart eval "$restart" exit $? } exit 0
Оставьте свой комментарий !

Ваше имя:
Комментарий:
Оба поля являются обязательными

 Автор  Комментарий к данной статье