Плохое электропитание, или «Грабли» с UPS. Подключение источника бесперебойного питания UPS Powercom KIN 625AP::Журнал СА 8.2003
www.samag.ru
     
Поиск   
              
 www.samag.ru    Web  0 товаров , сумма 0 руб.
E-mail
Пароль  
 Запомнить меня
Регистрация | Забыли пароль?
Журнал "Системный администратор"
Журнал «БИТ»
Наука и технологии
Подписка
Где купить
Авторам
Рекламодателям
Архив номеров
Контакты
   

  Опросы
  Статьи

Электронный документооборот  

5 способов повысить безопасность электронной подписи

Область применения технологий электронной подписи с каждым годом расширяется. Все больше задач

 Читать далее...

Рынок труда  

Системные администраторы по-прежнему востребованы и незаменимы

Системные администраторы, практически, есть везде. Порой их не видно и не слышно,

 Читать далее...

Учебные центры  

Карьерные мечты нужно воплощать! А мы поможем

Школа Bell Integrator открывает свои двери для всех, кто хочет освоить перспективную

 Читать далее...

Гость номера  

Дмитрий Галов: «Нельзя сказать, что люди становятся доверчивее, скорее эволюционирует ландшафт киберугроз»

Использование мобильных устройств растет. А вместе с ними быстро растет количество мобильных

 Читать далее...

Прошу слова  

Твердая рука в бархатной перчатке: принципы soft skills

Лауреат Нобелевской премии, специалист по рынку труда, профессор Лондонской школы экономики Кристофер

 Читать далее...

1001 и 1 книга  
19.03.2018г.
Просмотров: 9886
Комментарии: 0
Потоковая обработка данных

 Читать далее...

19.03.2018г.
Просмотров: 8100
Комментарии: 0
Релевантный поиск с использованием Elasticsearch и Solr

 Читать далее...

19.03.2018г.
Просмотров: 8200
Комментарии: 0
Конкурентное программирование на SCALA

 Читать далее...

19.03.2018г.
Просмотров: 5195
Комментарии: 0
Машинное обучение с использованием библиотеки Н2О

 Читать далее...

12.03.2018г.
Просмотров: 5873
Комментарии: 0
Особенности киберпреступлений в России: инструменты нападения и защита информации

 Читать далее...

Друзья сайта  

 Плохое электропитание, или «Грабли» с UPS. Подключение источника бесперебойного питания UPS Powercom KIN 625AP

Архив номеров / 2003 / Выпуск №8 (9) / Плохое электропитание, или «Грабли» с UPS. Подключение источника бесперебойного питания UPS Powercom KIN 625AP

Рубрика: Администрирование /  Оборудование

ПАВЕЛ ЗАКЛЯКОВ

Плохое электропитание, или  «грабли» с UPS

Подключение источника бесперебойного питания  UPS Powercom KIN 625AP

К сожалению, отечественные сети электропитания не обеспечивают достаточную стабильность подаваемого напряжения. Напряжение может изменяться по значению и пропадать на время от нескольких миллисекунд до нескольких часов без предварительного предупреждения. Данная нестабильность в электропитании есть следствие особенностей российского законодательства. В идеале проблемы и последствия сбоев электропитания должны решать страховые компании и юристы. Однако мы живем далеко не в идеальной стране, полной исключений. Все знают, что «русский сервис ненавязчив», и за разумные деньги выбирать особо не приходится.

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

Многие думают, что покупка ИБП (источников бесперебойного питания, UPS, Uninterruptable Power Supply) есть решение проблемы. Данная мысль правильная, и любой ИБП лучше, чем его отсутствие. Увы, но по моим наблюдениям, довольно много мелких серверов вообще не защищено ИБП. Хотелось бы администраторов таких серверов убедить в необходимости покупки и последующей правильной настройке ИБП, а данная статья поможет в этом. Надеюсь, что убеждать вас в том, что наличие ИБП в наших условиях необходимо, не стоит. Возникает вопрос: «А что купить?» На рынке полно моделей с различными ценами. Мой выбор пал на UPS Powercom KIN 625AP.

Рисунок 1

Рисунок 1

Данная модель наиболее оптимальна для одного компьютера-сервера без монитора. Менее емкие модели менее желательны, так как они не могут использоваться для подключения монитора. Их емкости хватит на несколько минут, и в момент включения монитора возможен значительный скачок напряжения, что приведет к перезапуску компьютера. А по закону подлости у вас обязательно возникнет необходимость администрирования с консоли, если вы рассчитываете, что вас эта ситуация обойдет стороной. Более емкие модели дороги, и их излишняя емкость не будет использоваться. Вопрос в выборе емкости не такой сложный. Другим критерием выбора ИБП является возможность создания обратной связи с компьютером и возможность управления. Есть модели с управлением и без него. Выбранная мной модель с управлением, и я вам советую брать такую же. Она стоит несколько дороже, зато это большой плюс, так как компьютер может оповещать администратора, сам выключаться и включаться.

Рисунок 2

Рисунок 2

В комплекте к UPS Powercom KIN 625A шли два сетевых кабеля на 220 вольт, телефонный кабель и кабель управления для подключения к COM-порту с разъемом DB-9. Защита телефонной линии пока мне не понадобилась, несмотря на наличие модема, но потенциально порадовала возможность использования ее в будущем.

Рисунок 3

Рисунок 3

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

Софта к ИБП под Linux на прилагаемом компакт-диске не было. Стандартные средства Linux мне настроить не удалось. Возможно, я с ними не до конца разобрался. Поэтому я начал свои поиски в Интернете и нашел следующие документы:

Более полная информация, правда уже на английском языке и без адаптации для UPS Powercom имеется на сайте Red Hat [4].

Я вкратце опишу, что было придумано и какие файлы надо создать и скомпилировать. Желающие могут поискать первоисточники самостоятельно. Однако в этих источниках не будет сделанных мною дополнений и исправлений.

В powerd-for-powercom-kin-ups.tar.gz имеются как программы, так и их исходники на С. Заранее скомпилированные файлы работают у меня без проблем.

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

Скорее всего, они должны работать не хуже готовых. Если будут проблемы, то их можно обсудить в форуме журнала (http://www.samag.ru/cgi-bin/yabb/YaBB.pl).

Дополнительные документацию и программы вы можете скачать с вышеупомянутых ссылок самостоятельно.

Итак, приступим.

Для работы с UPS используются две программы: первая, собственно, powerd – демон UPS. Вторая – poweroffups, котороя выключает UPS. Все должно работать с «родным» кабелем для подключения к COM-порту, если не работает – смотрите далее.

/*

 * powerd  Catch power failure signals from a Trust Energy Protector 400/650 and notify init

 *

 * Usage:  powerd /dev/cua3 (or any other serial device)

 *

 * Author: Ciro Cattuto <ciro@stud.unipg.it>

 *

 * Version 1.0 - 31 March 1997

 *

 * This code is heavily based on the original powerd.c code by Miquel van Smoorenburg <miquels@drinkel.ow.org>.

 *

 * This program is free software; you can redistribute it and/or modify it under the terms of the GNU  General Public License

 * as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.

 *

 * Update for PowerCom King Pro by Fedor Lizunkov  2:5020/960@Fidonet 24 May 2000

 */

/* state 0 - power is good */

#define T0_SLEEP 10     /* interval between port reads,in seconds */

#define T0_INL  3       /* number of seconds IN LINE has to be 0 to cause an action */

#define T0_BAT    3     /* number of seconds BATTERY has to be 0 to cause an action */

/* state 1 - power is failing */

#define T1_SLEEP  2     /* interval between ports reads */

#define T1_INL    3     /* same as T0_INL */

#define T1_BAT    3     /* same as T0_BAT */

#define NUMRECEIVEDBYTES  11   /* out date size from UPS */

#define REQ_01  0x01                  /* in date to UPS (request) */

#define REQ_03  0x03                  /* in date to UPS (self test) */

#define REQ_OFF 0xbc           /* first byte for UPS off  */

#define LINE_FAIL 0x01

#define BATT_LOW  0x02

#define UPS_OFF   0x80

#define BATT_BAD  0x02

/* Use the new way of communicating with init. */

#define NEWINIT

#include <sys/types.h>

#include <sys/stat.h>

#include <sys/ioctl.h>

#include <sys/termios.h>

#include <fcntl.h>

#include <errno.h>

#include <stdlib.h>

#include <unistd.h>

#include <stdio.h>

#include <signal.h>

#include <syslog.h>

#include <string.h>

#include "paths.h"

#ifdef NEWINIT

#include "initreq.h"

#endif

#ifndef SIGPWR

#  define SIGPWR SIGUSR1

#endif

#ifdef NEWINIT

void alrm_handler()

{

}

#endif

  /* Tell init that the power has gone (1), is back (0),  or the UPS batteries are low (2). */

void powerfail(int event)

{

    int fd;

#ifdef NEWINIT

    struct init_request req;

    /* Fill out the request struct. */

    memset(&req, 0, sizeof(req));

    req.magic = INIT_MAGIC;

    switch (event)

          {

          case 0:

                  req.cmd = INIT_CMD_POWEROK;

                  break;

          case 1:

                  req.cmd = INIT_CMD_POWERFAIL;

                  break;

          case 2:

          default:

                  req.cmd = INIT_CMD_POWERFAILNOW;

          }

    /* Open the fifo (with timeout) */

    signal(SIGALRM, alrm_handler);

    alarm(3);

    if ((fd = open(INIT_FIFO, O_WRONLY)) >= 0

         && write(fd, &req, sizeof(req)) == sizeof(req)) {

          close(fd);

          return;

    }

    /* Fall through to the old method.. */

#endif

    /* Create an info file for init. */

    unlink(PWRSTAT);

    if ((fd = open(PWRSTAT, O_CREAT|O_WRONLY, 0644)) >= 0) {

    switch (event)

          {

          case 0:

                  write(fd, "OK\n", 3);

                  break;

          case 1:

                  write(fd, "FAIL\n", 5);

                  break;

          case 2:

          default:

                  write(fd, "LOW\n", 4);

                  break;

          }

    close(fd);

    }

    kill(1, SIGPWR);

}

  /* Main program. */

int main(int argc, char *argv[])

{

    int fd;

    int dtr_bit = TIOCM_DTR;

    int rts_bit = TIOCM_RTS;

    int counter;

    int ret;

    unsigned char req_01 = REQ_01;

    unsigned char in;

    unsigned char buf[NUMRECEIVEDBYTES];

    int status = -1;

    int INL;

    int BAT;

    struct termios tio;

    int INL_count = 0, BAT_count = 0;

    int tries;

    if (argc < 2) {

          fprintf(stderr, "Usage: powerd <device>\n");

          exit(1);

    }

    /* Start syslog. */

    openlog("powerd", LOG_CONS|LOG_PERROR, LOG_DAEMON);

    /* Open monitor device. */

    if ((fd = open(argv[1], O_RDWR | O_NDELAY)) < 0) {

     syslog(LOG_ERR, "%s: %s", argv[1], sys_errlist[errno]);

          closelog();

          exit(1);

    }

    tcgetattr (fd, &tio);

    tio.c_cflag = B1200 | CS8 | CLOCAL | CREAD;

    tio.c_iflag = IGNPAR;

    tio.c_oflag = 0;

    tio.c_lflag = 0;

    tio.c_cc[VMIN] = 1;

    tio.c_cc[VTIME] = 0;

    tcflush (fd, TCIFLUSH);

    tcsetattr (fd, TCSANOW, &tio);

    /* DTR is low */

    ioctl(fd, TIOCMBIC, &dtr_bit);

    /* RTS is high */

    ioctl(fd, TIOCMBIS, &rts_bit);

    /* Daemonize. */

    switch(fork()) {

          case 0: /* Child */

                  closelog();

                  setsid();

                  break;

          case -1: /* Error */

                  syslog(LOG_ERR, "can't fork.");

                  closelog();

                  exit(1);

          default: /* Parent */

                  closelog();

                  exit(0);

    }

    /* Restart syslog. */

    openlog("powerd", LOG_CONS, LOG_DAEMON);

    /* Now sample the DCD line. */

    while(1) {

        tcflush (fd, TCIFLUSH);

        ret = write(fd, &req_01, 1);

        if (ret <= 0 ) {

            sleep(10);

            continue;

        }

        sleep(1);

        counter = 0;

        while (counter < NUMRECEIVEDBYTES) {

            ret = read(fd, &in, 1);

            if (ret <= 0) {

                status = -1;

                break;

            }

#ifdef DEBUG

            syslog(LOG_DEBUG, "in%d = 0x%x\n", counter, in);

#endif

            buf[counter] = in;

            counter++;

        }

  if ((buf[5] != 0) || (buf[7] != 0) || (buf[8] != 0)) {

    /* looks like a transfer error in serial data communication */

    syslog (LOG_WARNING, "Serial data from ups was invalid!");

            sleep(10);

            continue;

        }

        if (buf[10] & BATT_BAD) {

            syslog (LOG_WARNING, "UPS`s battery is bad!");

            sleep(10);

            continue;

        }

        INL = (buf[9] & LINE_FAIL) | (buf[9] & UPS_OFF);

        BAT = buf[9] & BATT_LOW;

#ifdef DEBUG

   syslog(LOG_DEBUG, "INL = 0x%x, BAT = 0x%x\n", INL, BAT);

#endif

    if (status == -1)

                  {

        status = (INL == 0) ? 0 : 1;

         if (INL)

                          {

             syslog(LOG_ALERT, "Power Failure. UPS active.");

                          powerfail(1);

                          }

                  }

          switch (status)

                  {

                  case 0:

                          if ((INL == 0) && (BAT == 0))

                                  {

                                  INL_count = 0;

                                  BAT_count = 0;

                                  sleep(T0_SLEEP);

                                  continue;

                                  }

                          if (INL != 0)

                                  INL_count++;

                          if (BAT != 0)

                                  BAT_count++;

                          if ((INL_count < T0_INL) && (BAT_count < T0_BAT))

             {

                sleep(1);

                continue;

                                  }

       if (BAT_count == T0_BAT)

                                  {

      status = 2;

         syslog(LOG_ALERT, "UPS batteries low!");

                                  break;

                                  }

             status = 1;

                INL_count = 0;

            syslog(LOG_ALERT, "Power Failure. UPS active.");

                break;

                  case 1:

                          if ((INL != 0) && (BAT == 0))

                                  {

                                  INL_count = 0;

                                  BAT_count = 0;

                                  sleep(T1_SLEEP);

                                  continue;

                                  }

                  if (INL == 0)

                    INL_count++;

                  if (BAT != 0)

                    BAT_count++;

        if ((INL_count < T1_INL) && (BAT_count < T1_BAT))

                                  {

                                  sleep(1);

                                  continue;

                                  }

                          if (BAT_count == T1_BAT)

                                  {

                                  status = 2;

                syslog(LOG_ALERT, "UPS batteries low!");

                                  break;

                                  }

                          status = 0;

                          INL_count = 0;

                          BAT_count = 0;

                          syslog(LOG_ALERT, "Power okay.");

                          break;

                  case 2:

                          sleep(1);

                          continue;

                  default:

                          break;

                  }

          powerfail(status);

 }

    /* Never happens */

    return(0);

}

Это powerd.с, его надо скомпилировать. Для этого необходимо найти у себя файл ititreq.h или установить его. У меня в RedHat 7.3 он находится на CD 4: в /SRPMS/SysVinit-2.84-2.src.rpm. Надо либо поставить SysVinit-2.84-2.src.rpm, либо переписать из него файл ititreq.h. Удобнее всего в mc зайти в этот файл, далее в sysvinit-2.84.tar.gz, в директории /sysvinit-2.84/sys с помощью клавиши F5 вытащить нужный файл и поместить его рядом с powerd.с. После необходимо дописать в powerd.с где-нибудь в начале:

/* This is the file needed by SysVInit */

#define PWRSTAT         "/etc/powerstatus"

Далее можно компилировать:

# gcc –c powerd.c

# gcc –o powerd powerd.o

либо:

# gcc powerd.c -o powerd

В стандартной установке RedHat 7.3 со средствами разработки и языком gcc проблем быть не должно.

После компиляции у вас появится файл powerd.

Запускать его нужно так:

# powerd /dev/ttyS?

где вместо ? следует указывать нужный порт(/dev/ttyS0 – означает, что ИБП подключён к COM1. Если у вас ИБП подключён к COM2, то, соответственно, надо писать /dev/ttyS1 и т. д.). У меня это дело запускается из /etc/rc.d/rc.local.

#!/bin/sh

#

# This script will be executed *after* all the other init scripts.

# You can put your own initialization stuff in here

# if you don't want to do the full Sys V style init stuff.

touch /var/lock/subsys/local

# Добавить в конец файла

# Add support for the UPS

echo "Starting powerd daemon..."

rm -f /etc/turnUPSoff

if [ -x /sbin/powerd ]; then

    /sbin/powerd /dev/ttyS0

fi

# отправка сообщения об успешном запуске,

# см. пояснения в конце статьи можно закомментировать

/sbin/pager/system_up

Файл /etc/turnUPSoff (его наличие) является флагом, который выставляется, если нужно выключить ИБП – удаляем его при старте системы.

Далее правим /etc/inittab, необходимо заменить то, что там есть по поводу питания на эти строчки:

# What to do when power fails (delayed shutdown).

pf::powerfail:/etc/powerfail

# If power is back before shutdown, cancel the running shutdown.

pg::powerokwait:/etc/powerokay

# If UPS batteries are getting low, do an immediate shutdown.

pc::powerfailnow:/etc/powerfailnow

Если закомментировать уже имеющиеся строчки, то должно получиться следующее:

#

# inittab This file describes how the INIT process

#         should set upthe system in a certain run-level.

#

# Author: Miquel van Smoorenburg,

#        <miquels@drinkel.nl.mugnet.org>

#         Modified for RHS Linux

#         by Marc Ewing and Donnie Barnes

#

# Default runlevel. The runlevels used by RHS are:

#   0 - halt (Do NOT set initdefault to this)

#   1 - Single user mode

#   2 - Multiuser, without NFS

#       The same as 3, if you do not have networking)

#   3 - Full multiuser mode

#   4 - unused

#   5 - X11

#   6 - reboot (Do NOT set initdefault to this)

#

id:3:initdefault:

# System initialization.

si::sysinit:/etc/rc.d/rc.sysinit

l0:0:wait:/etc/rc.d/rc 0

l1:1:wait:/etc/rc.d/rc 1

l2:2:wait:/etc/rc.d/rc 2

l3:3:wait:/etc/rc.d/rc 3

l4:4:wait:/etc/rc.d/rc 4

l5:5:wait:/etc/rc.d/rc 5

l6:6:wait:/etc/rc.d/rc 6

# Things to run in every runlevel.

ud::once:/sbin/update

# Trap CTRL-ALT-DELETE

ca::ctrlaltdel:/sbin/shutdown -t3 -r now

# What to do when power fails (delayed shutdown).

pf::powerfail:/etc/powerfail

# If power is back before shutdown, cancel the running shutdown.

pg::powerokwait:/etc/powerokay

# If UPS batteries are getting low, do an immediate shutdown.

pc::powerfailnow:/etc/powerfailnow

# When our UPS tells us power has failed, assume we have

# a few minutes of power left. 

# Schedule a shutdown for 2 minutes from now.

# This does, of course, assume you have powerd installed

# and your UPS connected and working correctly. 

#pf::powerfail:/sbin/shutdown -f -h +2 "Power Failure; System Shutting Down"

# If power was restored before

# the shutdown kicked in, cancel it.

#pr:12345:powerokwait:/sbin/shutdown -c "Power Restored; Shutdown Cancelled"

# Run gettys in standard runlevels

1:2345:respawn:/sbin/mingetty tty1

2:2345:respawn:/sbin/mingetty tty2

3:2345:respawn:/sbin/mingetty tty3

4:2345:respawn:/sbin/mingetty tty4

5:2345:respawn:/sbin/mingetty tty5

6:2345:respawn:/sbin/mingetty tty6

# Run xdm in runlevel 5

# xdm is now a separate service

x:5:respawn:/etc/X11/prefdm -nodaemon

Далее нам необходимо создать файлы:

  • /etc/powerfail – будет запускаться при пропадании напряжения;
  • /etc/powerokay – будет запускаться, если после пропадания напряжения питание восстановится, а компьютер к этому времени еще не выключится;
  • /etc/powerfailnow – будет запускаться, когда батарея ИБП села и долго не сможет работать в случае пропадания напряжения.

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

/etc/powerfail

#!/bin/sh

# файл /etc/powerfail запускается при пропадании электропитания

# Сбрасываем кэши и синхронизируем содержимое дисков с их частичными образами в памяти.

/bin/sync

# Проверяем, не запущена ли у нас программа shutdown, например, на выключение через сутки,

# если запущена, то вычисляем ее PID и завершаем ее. Вместо нее будет висеть экземпляр на завершение

# через 10 минут. В случае последующего возникновения питания завершенный экземпляр shutdown

# на выключение системы востановлен не будет, и система через сутки не выключится. Необходимо

# это учитывать дополнительно.

PID=`ps auxw | grep "shutdown" | grep -v grep | awk "{print $2}"`

if [ "$PID" != "" ]; then kill -9 $PID

fi

# создаем файл, служащий флагом выключения ИБП, в него пишем дату в формате RFC, чтобы нам потом

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

# ничего не писать, так как можно просто посмотреть время его создания.

date -R>/etc/turnUPSoff

# запускаем в фоновом режиме скрипт, осуществляющий сигнализацию о пропадании питания

/sbin/pager/power_fail &

# запускаем выключение системы с отсрочкой на 10 минут

/sbin/shutdown -t30 -r +10 "POWER FAILURE" 

/etc/powerokay

#!/bin/sh

# файл /etc/powerokay, запускается в случае возвращения электропитания

# завершается процесс powerfail, инициировавший запуск выключения питания,

# а вместе с ним и все его потомки, в том числе и запущенный из него shutdown

kill `ps auxw | grep "powerfail" | grep -v grep | awk "{print $2}"`

# Убирается флаг выключения ИБП при выключении системы.

rm -f /etc/turnUPSoff

# Посылается сообщение о восстановлении питания и система, при необходимости возвращается в уровень 3.

# Если на сервере есть надобность в запущенных X-Window, то следует внести изменения самостоятельно.

/sbin/shutdown -c "THE POWER IS BACK"

/sbin/init 3

# запускается скрипт, отсылающий сообщение о востановлении электропитания

/sbin/pager/power_okay

/etc/powerfailnow

#!/bin/sh

# файл /etc/powerfailnow, запускается при разряде батарей в ИБП

# Сбрасываем кэши и синхронизируем содержимое дисков с их частичными образами в памяти.

/bin/sync 

# Проверяем, не запущена ли у нас программа shutdown, например, на выключение через сутки,

# если запущена, то вычисляем ее PID и завершаем ее. Вместо нее будет висеть экземпляр

# на завершение через 10 минут. В случае последующего возникновения питания завершенный

# экземпляр shutdown на выключение системы восcтановлен не будет, и система через сутки не выключится.

# Необходимо это учитывать дополнительно.

PID=`ps auxw | grep "shutdown" | grep -v grep | awk "{print $2}"`

if [ "$PID" != "" ]; then kill -9 $PID

fi

# Создаем файл, служащий флагом выключения ИБП, в него пишем дату в формате RFC, чтобы потом было

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

# так как можно просто посмотреть время его создания.

date -R>/etc/turnUPSoff

# Запускаем команду на выключение системы прямо сейчас

/sbin/shutdown -r now "UPS batteries low. IMMEDIATE SHUTDOWN."

# Если успеваем, то посылаем сообщение администратору о том, что идет экстренное выключение, возможно,

# разумнее разместить отсылку сообщения о выключении перед командой на выключение, однако

# если батарея работает на последнем издыхании, то может этого не случиться, а компьютер не успеет

# выключиться правильно, что может привести к большим сбоям и потерям данных.

/sbin/pager/power_failnow

Этим файлам следует придать атрибут запускаемости:

# chmod +x /etc/powerfail

# chmod +x /etc/powerokay

# chmod +x /etc/powerfailnow

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

При выключении питания разумно выключить и сам ИБП, чтобы он не работал вхолостую (на ИБП без управления такое сделать сложно). Для этого необходимо скомпилировать файл poweroffups.c (Примечание: изначально файл назывался poweroff.c, но чтобы не возникало конфликтов, так как запускаемый файл poweroff уже есть, то я его переименовал.)

/* poweroffups program for UPS Powercom King Pro.

   (c) Fedor Lizunkov 2:5020/960@Fidonet

   26 May 2000                                  */

#include

#include

#include

#include

#include

#define PAUSE   15

#define REQ_OFF 0xbc

int main(int argc, char *argv[])

{

    int fd;

    unsigned char off = REQ_OFF;

    unsigned char pause = PAUSE;

 if (argc < 2) {

  fprintf(stderr, "Usage: poweroff [time(sec)] ");

          exit(1);

    } 

    /* Open monitor device. */

    if ((fd = open(argv[1], O_RDWR | O_NDELAY)) < 0) {

          exit(1);

    }

    if (argc > 2) {

        pause = (unsigned char)atoi(argv[2]);

    }

    write(fd, &off, 1);

    sleep(1/5);

    write(fd, &pause, 1); 

    close(fd);

    return 0;

}

либо:

# gcc poweroffups.с -o poweroffups

Готовый файл лучше записать в директорию /sbin, при необходимых требованиях безопасности, задав ему соответствующие атрибуты. Для его запуска ему надо передать два параметра:  первый – порт, к которому подключен ИБП и на который надо посылать сигнал, а второй – количество секунд, через которое следует выключить ИБП. Если число секунд не задано, то выключение происходит через 15 секунд.

Чтобы выключение ИБП происходило при выключении компьютера, необходимо подправить файл /etc/rc.d/init.d/halt, дописав туда следующие строчки в самом конце перед eval «$command $HALTARGS» или «eval $command –i –d –p»:

# Добавить в конец файла перед строкой

# "eval $command $HALTARGS" или "eval

$command -i -d -p"

# Is this a powerfail situation?

if [ -f /etc/turnUPSoff ]; then

    echo "Turning off UPS. Bye."

    /sbin/poweroffups /dev/ttyS0 5

#    exit 1

fi

Проверяется, установлен ли флаг на выключение, то есть имеется ли файл /etc/turnUPSoff. Далее при его наличии запускается программа, которая передает ИБП параметры на выключение, соответственно, /dev/ttyS0 также означает, что ИБП подключен к COM1, а 5 означает, что систему надо выключить через 5 секунд.

Теперь, после установки, когда в теории у вас все должно заработать (кроме пейджинга), давайте рассмотрим возможные проблемы, дабы избежать повторного «наступания на грабли».

Лично у меня после установки всего обеспечения по инструкции программа наотрез отказывалась видеть ИБП. Размышления методом исключения через некоторое время привели к мысли, что проблема в кабеле.

Рисунок 4

Рисунок 4

После чего мной были исследованы кабели от нескольких моделей, разных по емкости и годам выпуска. В результате выяснилось, что существует несколько различных разводок кабелей, и у меня как раз оказался не тот, который нужен. Возможно, если бы все заработало сразу, то я бы и не стал писать статью. Итак, далее (рис. 5, рис. 6) разводки. Если у кого окажется третья – напишите, будет интересно.

Рисунок 5. Разводка 1. (Работает). Разъемы DB-9, на одном разъеме написано KIN-1, также есть кабель с такой же разводкой, но без надписи KIN-1

Рисунок 5. Разводка 1. (Работает). Разъемы DB-9, на одном разъеме написано KIN-1, также есть кабель с такой же разводкой, но без надписи KIN-1

Рисунок 6. Разводка 2. (Не работает)

Рисунок 6. Разводка 2. (Не работает)

Если у вас компьютер новый (в корпусе ATX, рис. 7), то подключение осуществляется очень просто.

Рисунок 7

Рисунок 7

Рисунок 7

Если же у вас компьютер старый (в корпусе AT, рис. 8), то у вас наряду с 9-контактным разъемом для COM-порта (DB-9) может встретиться и 25-контактный (DB-25).

Рисунок 8

Рисунок 8

Для подключения к разъему DB-25 может использоваться переходник (рис. 9).

Рисунок 9

Рисунок 9

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

Таблица 1. Разводка и сигналы последовательного интерфейса (СОM-порта)

Таблица 1. Разводка и сигналы последовательного интерфейса (СОM-порта)

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

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

При пропадании напряжения сервер переходил в режим выключения, после ждал, что напряжение появится, и если оно минут через 10 не появлялось, то он сохранялся и выключался сам. При этом отключался и сам ИБП. Далее, при появлении напряжения все это дело включалось обратно, загружалось и работало. Небольшая сложность была только в настройках BIOS. Так как корпус у меня ATX, то для него можно прописать, как вести себя компьютеру в случае пропадания и после появления напряжения. Компьютер может перейти в то состояние в котором он был до исчезновения электропитания, то есть включиться, если был включен, или не включаться, если был выключен. Насколько я помню, пришлось включить режим включения при появлении напряжения после пропадания. Так как выключение ИБП случалось через 5 секунд, то компьютер успевал выключиться раньше и оказывался выключенным на момент снятия с него напряжения, поэтому после не включался. В общем, опытным путем за несколько минут вы разберетесь.

Если пропадает напряжение, то это уже неординарная ситуация, несмотря на то, что все может само работать, как описано выше. Это, скорее, небольшое ЧП, так как, во-первых, пропадает сервис. Каково, если у вас упадет веб-сервер, и вы потеряете вашу хорошую репутацию, часть клиентов и вместе с ними вашу выгоду. Во-вторых, не факт, что напряжение дадут в разумный срок. Даже у любого мощного дизельного генератора без обслуживания и дозаправки рано или поздно закончится солярка. В-третьих, может зависнуть и что-то другое, поэтому администратора лучше информировать о событиях, связанных с электропитанием. Логично, что проще всего это делать через почту, а почта может быть послана на SMS-шлюз или наш шлюз пейджинговой компании в качестве пейджингового сообщения. При наличии в системе sendmail, qmail или других почтовых программ (MTA, mail transfer agent) проблема решена, однако вопрос: «Что делать, если эти программы не должны стоять на сервере, скажем, в целях безопасности, либо для них нет места?». Выход из этой ситуации довольно простой – написать небольшой скрипт, например на Perl, который бы запускался в нужном случае, соединялся бы с заранее определенным SMTP-сервером, для которого можно настроить правила iptables, и отсылал бы сообщение. Возможно, кто-то полезным для себя в этой статье найдет только этот скрипт, хотя подобные вещи давно уже описаны в различной литературе и не раз [2]. Конечно, это порочный круг – слать сообщения об ошибках через сеть, может же не только питание пропасть, но и сеть как раз не работать. Об этом я упомянул в самом начале, когда говорил о возможности защиты телефонной линий от некоторых помех средствами вышенастроенного ИБП. Как вариант можно настроить модемное соединение, и сервер будет звонить альтернативному провайдеру, однако это тема отдельной статьи по вопросу организации сигнализации на основе резервных модемных каналов. Да и наличие отдельной свободной телефонной линии тоже не всегда имеется. Поэтому это не очень удачный выход. В таком случае лучше использовать мобильные терминалы вроде Siemens TC35 Terminal [3], подключаемые к COM-порту. Это небольшая коробочка, которая подключается к компьютеру, в нее вставляется обычная SIM-карта для работы GSM-телефонов. К сожалению, терминала, работающего со стандартом CDMA, я пока не видел и не слышал о существовании такового. Далее, компьютер с помощью набора своеобразных at-команд (GSM 07.05) может посылать вам на телефон SMS более быстрым и надежным путем, исключая многие недостаточно надежные элементы. Значительно повышается вероятность доставки, так как из общей вероятности отказа исключаются вероятности того, что небудут работать модем, телефонная линия, коммутаторы на АТС, модемы провайдера, непосредственно отсылающего вам SMS, телефонная линия будет занята и т. д. Кому-то это может показаться дорого (около $250 за терминал) плюс ежемесячная абонентская плата сотовому оператору, либо большой кредит. Следует заметить что, какой-нибудь Pentium 100 может быть еще долго вполне жизнеспособен и по цене быть гораздо дешевле этого самого терминала. Вопрос же абонентской платы при желании можно попробовать решить созданием дубликата SIM-карты, однако не всякий провайдер поддержит такое начинание и будет гарантировать надежную работу. Многие умудряются переделать старые мобильные телефоны для этого, цена от этого получается меньше, надежность тоже несколько ниже. Как обойти проблему порочного круга при минимуме затрат – это уже другой вопрос, к этой статье прямо не относящийся. При необходимости наш народ обязательно что-то придумает, ну а вот ниже, собственно, скрипт, осуществляющий отсылку сообщений:

#!/usr/local/bin/perl

use Socket;

$pagermail="xxxxxx@xxxxxxxx.ru";

$pagersmtp="XX.XX.XX.XX"; 

 $from="server@yyyyyyyy.ru";

 $subject ="Server power fail!";

 $date = localtime time;

########### Send to pager ###########

socket(SMTP, PF_INET(), SOCK_STREAM(),6);

connect(SMTP,sockaddr_in(25,inet_aton($pagersmtp)));

recv(SMTP, $buffer, 200, 0);

send(SMTP, "HELO pasha ",0);

recv(SMTP, $buffer, 200, 0); 

send(SMTP, "MAIL FROM: <$from> ",0);

recv(SMTP, $buffer, 200, 0); 

send(SMTP, "RCPT TO: <$pagermail> ",0);

recv(SMTP, $buffer, 200, 0); 

send(SMTP, "DATA ",0);

recv(SMTP, $buffer, 200, 0);

send(SMTP, "From: $from ",0);

send(SMTP, "To: $pagermail ",0);

send(SMTP, "Subject: $subject ",0);

send(SMTP, "Mime-Version: 1.0 ",0);

send(SMTP, "Content-Type: text/plain; charset=koi8-r ",0);

send(SMTP, "Content-Transfer-Encoding: 8bit ",0);

send(SMTP, " ",0);

send(SMTP, "Power failure. System going to  gеренос строки

poweroff in 10 minutes. $date ",0);                              

send(SMTP, " . ",0);

recv(SMTP, $buffer, 200, 0);

#print "SMTP answer on message to pager: $buffer ";

send(SMTP, "QUIT ",0);

recv(SMTP, $buffer, 200, 0);

close (SMTP);

В нем необходимо вначале вписать адрес SMTP-сервера, который вас пустит к себе и разрешит вам отправлять сообщения $pagermail="xxxxxx@xxxxxxxx.ru"; и вписать адрес, на который вы собираетесь посылать сообщения.

$pagersmtp="XX.XX.XX.XX";

Еще следует подправить обратный адрес, который будет подставляться в ваши письма:

$from="server@yyyyyyyy.ru";

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

Для диагностики можно раскомментировать строчку, где выводится ответ от сервера. Скорее всего, эта информация попадет на консоль и в /var/log/messages, будучи перенаправленной средствами вне этого скрипта.

Данный файл следует сделать запускаемым:

# chmod +x power_fail

и поместить в директорию /sbin/pager, куда на него уже ссылается файл powerfail. При повышенных требованиях к безопасности следует не забыть установить требуемые атрибуты у файла.

Данный файл надо запускать из /etc/powerfail, лучше фоновым процессом /sbin/pager/power_fail & перед /sbin/shutdown –t30 –r +10 "POWER FAILURE", тогда не будет подвисания системы, если вдруг чего-то не отошлется. Иначе управление ко второй строке может придти не сразу.

Рисунок 10

Рисунок 10

Аналогичные файлы создаются и на случай появления напряжения после пропадания power_okay и на случай разрядки батарей при пропадании напряжения power_failnow.

Разумно также составить файл, который будет запускаться при загрузке системы, например, он будет называться system_up и будет запускаться из /etc/rc.d/rc.local, см. выше. Считаю необходимым это сделать по той причине, что перезагрузка реально работающего сервера вручную администратором происходит очень редко, реже чем раз в полгода и то при профилактическом обслуживании. Поэтому случаи перезагрузки можно рассматривать на уровне с таким ЧП, как пропадание электропитания, если не более существенным.

Литература:

  1. Борзенко А.Е. IBM PC: устройство, ремонт, модернизация. – 2-е  изд., перераб. и доп. – М.:ТОО фирма «Компьютер Пресс», 1996.
  2. Касперски К. Техника сетевых атак. Том 1. – М.: СОЛОН-Р, 2001.
  3. SIEMENS TC35 Терминал (функциональные возможности), http://www.olicom.spb.ru/ts35_4.html , 2003.
  4. The UPS Howto: http://www.europe.redhat.com/documentation/HOWTO/UPS-HOWTO-8.php3http://www.europe.redhat.com/documentation/HOWTO/UPS-HOWTO.php3, 2003.
  5. Тейнсли Д. Linux и UNIX: программирование в shell. Руководство разработчика: Пер. с англ. – К.: Издательская группа BHV, 2001.
  6. Митчел М., Оулдем Д., Самьюэл А. Программирование для Linux. Профессиональный подход.: Пер. с англ. – М.: Издательский дом «Вильямс», 2002.

Комментарии отсутствуют

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

Комментарии могут оставлять только зарегистрированные пользователи

               Copyright © Системный администратор

Яндекс.Метрика
Tel.: (499) 277-12-41
Fax: (499) 277-12-45
E-mail: sa@samag.ru