Управление сервисами биллинговой системы в ОС Solaris 10

В ОС Solaris 10 появилась новая подсистема управления сервисами - System Management Facility (SMF). Так как все сервисы, описываемые тут, идентичны с точки зрения SMF, то в этом документе рассмотрен пример реализации управления запуском одного сервиса на примере сервера MySQL и описан минимум команд для управления сервисом.

[NetUP (info AT netup.ru)]

В ОС Solaris 10 появилась новая подсистема управления сервисами - System Management Facility (SMF) [1], позволяющая лучше контролировать запуск и остановку сервисов биллинговой системы. Преимуществами данной подсистемы является:

  • Отсутствует необходимость запускать дополнительный контролирующий процесс (watchdog). В случае если все процессы сервиса по каким-то причинам завершают работу, его перезапуск выполняется автоматически и немедленно.
  • Также отпадает необходимость контролировать порядок запуска сервисов и перезапуска зависимых сервисов - достаточно описать зависимости сервисов, и какие действия выполнять в случае останова <главного> сервиса. Система все будет делать автоматически.
  • Если при запуске сервиса обнаружится ошибка, из-за которой не происходит нормальный запуск, то он переводится в состояние, предотвращающее дальнейшие бесполезные попытки его запуска.

Так как все сервисы, описываемые тут, идентичны с точки зрения SMF, то в этом документе рассмотрен пример реализации управления запуском одного сервиса на примере сервера MySQL и описан минимум команд для управления сервисом.

Также приведены листинги необходимых файлов для запуска остальных сервисов биллинговой системы с помощью SMF. В дополнение приведен листинг функции notify_admin, которая определена в файле /netup/utm5/smf/mail.sh. Данная функция предназначена для отправки сообщений по электронной почте администратору. Эта функция используется для информирования администратора об остановах сервисов биллинговой системы, при этом дополнительно в электронном письме можно высылать определенное администратором количество последних строк из журнальных файлов сервиса на момент останова. Таким образом, администратор получит важную информацию по работе сервиса и своевременно сможет принять меры для устранения неполадок.

База данных MySQL

Предварительно необходимо произвести установку сервера базы данных MySQL, произвести инициализацию базы, запустить сервер и проверить работоспособность. Далее будет рассмотрен процесс интегрирования MySQL в подсистему управления процессами ОС Solaris 10.

Описания и параметры запуска всех сервисов, запуском которых занимается SMF, хранятся в репозитарии и могут быть просмотрены и отредактированы с помощью программы svccfg(1M).

Чтобы добавить сервис в репозитарий SMF необходимо создать его <манифест> (manifest) - файл в формате XML, описывающий параметры запуска сервиса, и <метод> (method) - это может быть любая команда. В данном примере метод представляет собой скрипт на языке Bourne Shell.

Создадим манифест для сервера MySQL как указано в листинге 1.1. Манифесты хранятся в каталоге /var/svc/manifest и разделены по категориям (подкаталогам). Эти категории созданы только для удобства администратора. Подходящей категорией для сервера баз данных является application, а для сервисов UTM5 создадим отдельную категорию, например utm.

Листинг 1.1 - файл /var/svc/manifest/application/mysql.xml
<?xml version='1.0'?>
<!DOCTYPE service_bundle SYSTEM '/usr/share/lib/xml/dtd/service_bundle.dtd.1'>
<service_bundle type='manifest' name='mysql:mysql'>
<!-- Имя сервиса -->
        <service
                name='application/mysql'
                type='service'
                version='1'>
                <create_default_instance enabled='false' />
                <single_instance />
<!-- Зависимости. 
Если сервисы обозначеные как зависимости не работают - сервис не должен запускатся.-->
                <dependency name='fs'
                        grouping='require_all'
                        restart_on='none'
                        type='service'>
                        <service_fmri value='svc:/system/filesystem/local' />
                </dependency>
                <dependency name='net'
                        grouping='require_all'
                        restart_on='none'
                        type='service'>
                        <service_fmri value='svc:/network/loopback' />
                </dependency>
<!-- Команды для запуска. 
Обратите внимание, что здесь же задается имя пользователя от которого команда будет выполнена. -->
                <exec_method
                        type='method'
                        name='start'
                        exec='/lib/svc/method/svc-mysql start'
                        timeout_seconds='-1'>
                        <method_context>
                                <method_credential user='mysql' group='mysql' />
                        </method_context>
                </exec_method>
                <exec_method
                        type='method'
                        name='stop'
                        exec=':kill'
                        timeout_seconds='-1'>
                </exec_method>
        </service>
</service_bundle>

После этого необходимо создать <метод>, который будет использоваться для запуска сервера базы данных как указано в листинге 1.2.
Методы обычно расположены в каталоге /lib/svc/method.

Листинг 1.2 - файл /lib/svc/method/svc-mysql
#!/sbin/sh
# mysql
# 
# Пути к файлам необходимо заменить соответственно конфигурации
#

. /lib/svc/share/smf_include.sh

DB_DIR=/var/mysql
PID_FILE=${DB_DIR}/`/usr/bin/uname -n`.pid

case "$1" in
        start)
        /usr/local/mysql/bin/mysqld_safe --user=mysql --datadir=${DB_DIR} \
					--pid-file=${PID_FILE} > /dev/null &
        ;;

        stop)
        if [ -f ${PID_FILE} ]; then
                /usr/bin/pkill mysqld_safe > /dev/null 2>&1
                /usr/bin/kill `cat ${PID_FILE}` > /dev/null 2>&1 && echo -n mysql
        fi
        ;;

        'restart')
        stop
        while pgrep mysqld > /dev/null
        do
                sleep 1
        done
        start
        ;;
        *)
        echo "Usage: `basename $0` {start | stop | restart}"
        exit 64
        ;;
esac

После этого необходимо установить корректные права доступа  командами:

chown root:sys /var/svc/manifest/application/mysql.xml
chmod 444 /var/svc/manifest/application/mysql.xml
chown root:bin /lib/svc/method/svc-mysql
chmod 555 /lib/svc/method/svc-mysql

Проверить корректность настроек можно командой:

svccfg validate /var/svc/manifest/application/mysql.xml && echo OK

OK

Далее необходимо произвести импорт данных из XML файла в репозитарий командой:

svccfg import /var/svc/manifest/application/mysql.xml

Запуск сервиса можно произвести командой:

svcadm -v enable mysql

при этом вывод должен содержать строку:

svc:/application/mysql:default enabled.

Проверить запустился ли сервис можно командой:

svcs -a | grep mysql

При успешном запуске вывод должен содержать строку:

online         12:29:59  svc:/application/mysql:default

Для просмотра детальной информации о сервисе следует воспользоваться следующей командой:

svcs -x mysql

вывод этой команды:

svc:/application/mysql:default (?)
 State: online since Tue Dec 27 12:18:40 2005
   See: /var/svc/log/application-mysql:default.log
Impact: None.

Чтобы увидеть список процессов запущенных сервисом, воспользуйтесь следующей командой:

svcs -p mysql

Вывод содержит следующую информацию:

STATE          STIME    FMRI

online         Dec_27   svc:/application/mysql:default

               Dec_27        212 mysqld_safe

               Dec_27        291 mysqld

В случае необходимости становить сервис можно командой:

svcadm -v disable mysql

Если во время запуска произошла ошибка и сервис не смог запуститься, например из-за ошибки в конфигурации, подсистема SMF переводит его в состояние maintenance и после этого сервис не запустится командой svcadm enable. Для того чтобы запустить сервис после устранения ошибки, необходимо сначала <сбросить> его состояние командой:

svcadm clear mysql

Для каждого сервиса ведется свой журнал событий. Журналы располагаются в каталоге /var/svc/log.

Рекомендуется, также, изучить страницы справочного руководства man к приведенным командам. На этом интеграция сервера базы данных MySQL в подсистему SMF завершена.

База данных PostgreSQL

База данных PostgreSQL интегрируется аналогично базе данных MySQL. Ниже приведены листинги соответствующих файлов.

Листинг 2.1 - файл /var/svc/manifest/application/pgsql.xm
<?xml version='1.0'?>
<!DOCTYPE service_bundle SYSTEM '/usr/share/lib/xml/dtd/service_bundle.dtd.1'>
<service_bundle type='manifest' name='postgresql:postgresql'>
        <service
                name='application/pgsql'
                type='service'
                version='1'>
                <create_default_instance enabled='false' />
                <single_instance />
                <dependency name='fs'
                        grouping='require_all'
                        restart_on='none'
                        type='service'>
                        <service_fmri value='svc:/system/filesystem/local' />
                </dependency>
                <dependency name='net'
                        grouping='require_all'
                        restart_on='none'
                        type='service'>
                        <service_fmri value='svc:/network/loopback' />
                </dependency>
<!-- Обратите внимание на имя пользователя. Замените соответственно вашей конфигурации. -->
                <exec_method
                        type='method'
                        name='start'
                        exec='/lib/svc/method/svc-pgsql start'
                        timeout_seconds='-1'>
                        <method_context>
                                <method_credential user='postgres' group='postgres' />
                        </method_context>
                </exec_method>
                <exec_method
                        type='method'
                        name='stop'
                        exec='/lib/svc/method/svc-pgsql stop'
                        timeout_seconds='-1'>
                        <method_context>
                                <method_credential user='postgres' group='postgres' />
                        </method_context>
                </exec_method>
       </service>
</service_bundle>
Листинг 2.2 - файл /lib/svc/method/svc-pgsq
#!/sbin/sh
#
# PostgreSQL Method
#

. /lib/svc/share/smf_include.sh

PGPREFIX=/usr/local/pgsql
PGHOME=/var/pgsql
PGDATADIR=$PGHOME/data
PGLOG=$PGHOME/pgsql.log

case "$1" in
        'start')
        [ -x $PGPREFIX/bin/pg_ctl ] && $PGPREFIX/bin/pg_ctl -D $PGDATADIR -l $PGLOG start
        sleep 3
        pgrep -x postgres && exit $SMF_EXIT_OK
        exit $SMF_EXIT_ERR_FATAL
        ;;
        'stop')
        $PGPREFIX/bin/pg_ctl stop -D "$PGDATADIR" -s -m fast
        [ $? -eq 0 ] && exit $SMF_EXIT_OK
        exit $SMF_EXIT_ERR_OTHER
        ;;
        *)
                echo "sfm."
        ;;
esac

Ядро биллинговой системы utm5_core

Интеграция сервисов биллинговой системы производится аналогично серверу базы данных. Ниже приводятся листинги соответствующих файлов.

Листинг 3.1 - файл /var/svc/manifest/utm/utm5_core.xm
<?xml version='1.0'?>
<!DOCTYPE service_bundle SYSTEM '/usr/share/lib/xml/dtd/service_bundle.dtd.1'>
<service_bundle type='manifest' name='UTM5:utm5_core'>
        <service
                name='utm/utm5_core'
                type='service'
                version='1'>
                <create_default_instance enabled='false' />
                <single_instance />
                <!-- Cannot work without application -->
                <dependency
                        name='mysql'
                        grouping='require_all'
                        restart_on='restart'
                        type='service'>
                        <service_fmri value='svc:/application/mysql' />
                </dependency>
                <exec_method
                        type='method'
                        name='start'
                        exec='/lib/svc/method/svc-utm5_core start'
                        timeout_seconds='120'>
                        <method_context>
                                <method_credential user='root' group='root' />
                        </method_context>
                </exec_method>
                <exec_method
                        type='method'
                        name='stop'
                        exec='/lib/svc/method/svc-utm5_core stop %{restarter/contract}'
                        timeout_seconds='120'>
                        <method_context>
                                <method_credential user='root' group='root' />
                        </method_context>
                </exec_method>
                <template>
                        <common_name>
                                <loctext xml:lang='C'>
                                        NetUP UTM5 core
                                </loctext>
                        </common_name>
                        <description>
                                <loctext xml:lang='C'>
                                        The Core of UTM5 System
                                </loctext>
                        </description>
                        <documentation>
                                <doc_link name='netup.ru'
                                        uri='http://www.netup.ru' />
                        </documentation>
                </template>
        </service>
</service_bundle>

Листинг 3.2 - файл /lib/svc/method/svc-utm5_coe
#!/sbin/sh
#
# NetUP UTM 5 Core Method
#

. /lib/svc/share/smf_include.sh
. /netup/utm5/smf/mail.sh

CFGFILE=/netup/utm5/utm5.cfg
[ ! -f $CFGFILE ] && exit $SMF_EXIT_ERR_CONFIG
. $CFGFILE

BINDIR=/netup/utm5/bin
EXEC=utm5_core

[ ! -x $BINDIR/$EXEC ] && exit $SMF_EXIT_ERR_CONFIG

PIDFILE=${core_pid_file:-/var/run/utm5_core.pid}
MAINLOG=${log_file_main:-/netup/utm5/log/main.log}
SVCLOG="/var/svc/log/utm-utm5_core:default.log"

check_and_kill ()
{
        PID=`head -1 $1`
        kill -0 $PID > /dev/null 2>&1
        [ $? -eq 0 ] && kill -USR1 $PID
}

case "$1" in
        'start')
                [ -x $BINDIR/$EXEC ] && $BINDIR/$EXEC &
                sleep 5

                if kill -0 $! > /dev/null 2>&1 ; then
                        echo "Success."
                        exit $SMF_EXIT_OK
                else
                        echo "Error."
                        exit $SMF_EXIT_ERR_FATAL
                fi
        ;;

        'stop')

                # Kill process
                [ -f $PIDFILE ] && check_and_kill $PIDFILE
                sleep 10
                [ -f $PIDFILE ] && rm -f $PIDFILE

                # Notify admins about service stop
                notify_admin E "UTM5 Core exited!" "${SVCLOG}.40" "${MAINLOG}.30"
                smf_kill_contract $2 KILL 1
        ;;

        *)
                echo "Usage: `basename $0` {start | stop}"
        ;;
esac

RADIUS-сервер utm5_radius

Листинг 4.1 - файл /var/svc/manifest/utm/utm5_radius.xm
<?xml version='1.0'?>
<!DOCTYPE service_bundle SYSTEM '/usr/share/lib/xml/dtd/service_bundle.dtd.1'>
<service_bundle type='manifest' name='netup:utm5_radius'>
        <service
                name='utm/utm5_radius'
                type='service'
                version='1'>
                <create_default_instance enabled='false' />
                <single_instance />

                <!-- Cannot work without utm5_core -->

                <dependency
                        name='utm5_core'
                        grouping='require_all'
                        restart_on='restart'
                        type='service'>
                        <service_fmri value='svc:/utm/utm5_core' />
                </dependency>

                <!-- Execution methods -->
                <exec_method
                        type='method'
                        name='start'
                        exec='/lib/svc/method/svc-utm5_radius start'
                        timeout_seconds='120'>
                        <method_context>
                                <method_credential user='root' group='root' />
                        </method_context>
                </exec_method>
                <exec_method
                        type='method'
                        name='stop'
                        exec='/lib/svc/method/svc-utm5_radius stop %{restarter/contract}'
                        timeout_seconds='120'>
                </exec_method>
                <template>
                        <common_name>
                                <loctext xml:lang='C'>
                                        NetUP UTM5 radius
                                </loctext>
                        </common_name>
                        <documentation>
                                <doc_link name='netup.ru'
                                        uri='http://www.netup.ru' />
                        </documentation>
                </template>
        </service>
</service_bundle>

Листинг 4.2 - файл /lib/svc/method/svc-utm5_radiu

#!/sbin/sh
#
# Radius method
#

. /lib/svc/share/smf_include.sh
. /netup/utm5/smf/mail.sh

CFGFILE=/netup/utm5/radius5.cfg

[ ! -f $CFGFILE ] && exit $SMF_EXIT_ERR_CONFIG

. $CFGFILE

MAINLOG=${log_file_main:-/netup/utm5/log/radius_main.log}
BINDIR=/netup/utm5/bin
EXEC=utm5_radius
PIDFILE=/var/run/utm5_radius.pid
SVCLOG="/var/svc/log/utm-utm5_radius:default.log"
PING=core_ping

case "$1" in
  'start')
    [ -x $BINDIR/$PING -a -x $BINDIR/$EXEC ] && PING_ARGS="-h ${core_host:-127.0.0.1} \
-P ${core_port:-11758} -l ${radius_login:-radius} -p ${radius_password:-radius} -i 2 -c 1"
    if [ -n "$PING_ARGS" ]; then
      $BINDIR/$PING $PING_ARGS && $BINDIR/$EXEC &
      sleep 3
      kill -0 $! || exit $SMF_EXIT_ERR_FATAL
      exit $SMF_EXIT_OK
    else
      exit $SMF_EXIT_ERR_CONFIG
    fi
  ;;
  'stop')
    notify_admin W "Radius exited!" "${SVCLOG}.40" "${MAINLOG}.30"
    smf_kill_contract $2 KILL 1 && rm -f $PIDFILE && exit $SMF_EXIT_OK
  ;;
  *)
    echo "Usage: `basename $0` {stop|start}"
  ;;
esac

Сервис utm5_rfw

Листинг 5.1 - файл /var/svc/manifest/utm/utm5_rfw.xm
<?xml version='1.0'?>
<!DOCTYPE service_bundle SYSTEM '/usr/share/lib/xml/dtd/service_bundle.dtd.1'>
<service_bundle type='manifest' name='netup:utm5_rfw'>
        <service
                name='utm/utm5_rfw'
                type='service'
                version='1'>

                <create_default_instance enabled='false' />
                <single_instance />

                <!-- Cannot work without utm5_core -->

                <dependency
                        name='utm5_core'
                        grouping='require_all'
                        restart_on='restart'
                        type='service'>
                        <service_fmri value='svc:/utm/utm5_core' />
                </dependency>

                <!-- Execution methods -->

                <exec_method
                        type='method'
                        name='start'
                        exec='/lib/svc/method/svc-utm5_rfw start'
                        timeout_seconds='120'>
                        <method_context>
                                <method_credential user='root' group='root' />
                        </method_context>
                </exec_method>

                <exec_method
                        type='method'
                        name='stop'
                        exec='/lib/svc/method/svc-utm5_rfw stop %{restarter/contract}'
                        timeout_seconds='120'>
                </exec_method>

                <template>
                        <common_name>
                                <loctext xml:lang='C'>
                                        NetUP UTM5 rfw
                                </loctext>
                        </common_name>
                        <documentation>
                                <doc_link name='netup.ru'
                                        uri='http://www.netup.ru' />
                        </documentation>
                </template>
        </service>
</service_bundle>
Листинг 5.2 - файл /lib/svc/method/svc-utm5_rf
#!/sbin/sh
#
# UTM5 rfw method
#

. /lib/svc/share/smf_include.sh
. /netup/utm5/smf/mail.sh

CFGFILE=/netup/utm5/rfw5.cfg
[ ! -f $CFGFILE ] && exit $SMF_EXIT_ERR_CONFIG
. $CFGFILE

MAINLOG=${log_file_main:-/netup/utm5/log/rfw_main.log}
BINDIR=/netup/utm5/bin
EXEC=utm5_rfw
EXEC_FLAGS="-f"
PIDFILE=/var/run/utm5_rfw.pid
SVCLOG="/var/svc/log/utm-utm5_rfw:default.log"

case "$1" in
        'start')
                [ -x $BINDIR/$EXEC ] && $BINDIR/$EXEC $EXEC_FLAGS &
                sleep 3
                kill -0 $! || exit $SMF_EXIT_ERR_FATAL
                exit $SMF_EXIT_OK
        ;;
        'stop')
                notify_admin W "UTM5 RFW exited!" "${SVCLOG}.40" "${MAINLOG}.30"
                smf_kill_contract $2 KILL 1 && rm -f $PIDFILE && exit $SMF_EXIT_OK
        ;;
        *)
                echo "Usage: `basename $0` {stop|start}"
        ;;
esac

Сервис utm5_rapida_check

Листинг 6.1 - файл /var/svc/manifest/utm/utm5_rapida_check.xml
<?xml version='1.0'?>
<!DOCTYPE service_bundle SYSTEM '/usr/share/lib/xml/dtd/service_bundle.dtd.1'>
<service_bundle type='manifest' name='netup:utm5_rapida_check'>
        <service
                name='utm/utm5_rapida_check'
                type='service'
                version='1'>
                <create_default_instance enabled='false' />
                <single_instance />

                <!-- Cannot work without utm5_core -->

                <dependency
                        name='utm5_core'
                        grouping='require_all'
                        restart_on='restart'
                        type='service'>
                        <service_fmri value='svc:/utm/utm5_core' />
                </dependency>

                <!-- Execution methods -->
                <exec_method
                        type='method'
                        name='start'
                        exec='/lib/svc/method/svc-utm5_rapida_check start'
                        timeout_seconds='120'>
                        <method_context>
                                <method_credential user='root' group='root' />
                        </method_context>
                </exec_method>
                <exec_method
                        type='method'
                        name='stop'
                        exec='/lib/svc/method/svc-utm5_rapida_check stop %{restarter/contract}'
                        timeout_seconds='120'>
                </exec_method>
                <template>
                        <common_name>
                                <loctext xml:lang='C'>
                                        NetUP UTM5 Rapida Check
                                </loctext>
                        </common_name>
                        <documentation>
                                <doc_link name='netup.ru'
                                        uri='http://www.netup.ru' />
                        </documentation>
                </template>
        </service>
</service_bundle>
Листинг 6.2 - файл /lib/svc/method/svc-utm5_rapida_check
#!/sbin/sh
#
# Rapida Check method
#

. /lib/svc/share/smf_include.sh
. /netup/utm5/smf/mail.sh

CFGFILE=/netup/utm5/rapida5.cfg
[ ! -f $CFGFILE ] && exit $SMF_EXIT_ERR_CONFIG

BINDIR=/netup/utm5/bin
EXEC=utm5_rapida_check
SVCLOG="/var/svc/log/utm-utm5_rapida_check:default.log"

case "$1" in
        'start')
                [ -x $BINDIR/$EXEC ] && $BINDIR/$EXEC $CFGFILE &
                sleep 3
                kill -0 $! || exit $SMF_EXIT_ERR_FATAL
                exit $SMF_EXIT_OK
        ;;
        'stop')
                notify_admin W "UTM5 Rapida Check exited!" "${SVCLOG}.40"
                smf_kill_contract $2 KILL 1 && exit $SMF_EXIT_OK
        ;;
        *)
                echo "Usage `basename $0` {stop|start}"
        ;;
esac

Функция notify_admin

Листинг 7.1 - файл /netup/utm5/smf/mail.sh
#!/sbin/sh
# Copyright (c) 2001-2005 NetUP Inc. . All rights reserved.
#
# Common variables
# ----------------
#
notify_admin_ARGS=$@
# Укажите адреса электронной почты администратора. 
# По этим адресам будут приходить уведомления.
MAIL_ADMIN_MAIL=any@email.address
MAIL_COPY_TO=another@email.address

# Function
# ========
# Name: notify_admin ()
# Descr: Sends formatted email to admin
# Version: 0.2
# Usage: notify_admin [type] [subject] [message] [logfile.lines ...]
#        [type]     char      {E|W|N} ERROR, WARNING, NOTICE respectively. Default "INFO".
#        [subject]  string    Subject. If contains spaces MUST be "QUOTED".
#        [message]  string    Message body. If contains spaces MUST be "QUOTED".
#        [logfile.lines ...]  string  Last $lines to be included into message body of the $logfile
#                                     (`tail -$lines $logfile' used)
# All parameters are optional.
#
notify_admin ()
{
  #
  # Initialize some variables
  # -------------------------
  notify_admin_ADMIN_MAIL=${MAIL_ADMIN_MAIL:-root}
  notify_admin_COPY_TO=$MAIL_COPY_TO
  notify_admin_STATUS="INFO"
  notify_admin_SUBJECT=""
  notify_admin_MESSAGE=""
  notify_admin_MAILER_ARGS=""
  #
  # If command line contains status
  # -------------------------------
  case "$1" in
    'E')
      notify_admin_STATUS="ERROR"
      shift
    ;;
    'W')
      notify_admin_STATUS="WARNING"
      shift
    ;;
    'N')
      notify_admin_STATUS="NOTICE"
      shift
    ;;
    esac

    #
    # Set notify_admin_SUBJECT and notify_admin_MESSAGE variables
    # -------------------------------------------
    #
    while echo "$1" | egrep -v  '^[^ ]*\.[0-9]?+$' > /dev/null 2>&1
    do
      if [ -z "$notify_admin_SUBJECT" ]; then
        notify_admin_SUBJECT="$1"
        shift
        continue
      fi
      if [ -z "$notify_admin_MESSAGE" ]; then
        notify_admin_MESSAGE="${1}\n"
        shift
        continue
      fi
      break
    done

    #
    # Check other arguments if any and prepare message
    # ------------------------------------------------
    if [ -n "$1" ]; then
      for opt in "$@"
      do
        notify_admin_NUM_LINES=`echo "$opt" | grep -v ' ' | awk -F. '{ print $NF }' \
| egrep '^[0-9]?+$' 2>/dev/null`
        if [ $? -ne 0 -o -z "$notify_admin_NUM_LINES" ]; then
          continue
        else
          #
          # work with the argument as it is a logfile.
          # ------------------------------------------
          notify_admin_LOG_FNAME=`echo "$opt" | sed "s/\.${notify_admin_NUM_LINES}$//;"`
          [ -f "$notify_admin_LOG_FNAME" ] || { notify_admin_MESSAGE="${notify_admin_MESSAGE}\
\n---\n${notify_admin_LOG_FNAME} does not exist.\n\n"; continue; }
          [ -r $notify_admin_LOG_FNAME ] || { notify_admin_MESSAGE="${notify_admin_MESSAGE}\
\n---\n${notify_admin_LOG_FNAME} is not readable.\n\n"; continue; }
          [ -s $notify_admin_LOG_FNAME ] || { notify_admin_MESSAGE="${notify_admin_MESSAGE}\
\n---\n${notify_admin_LOG_FNAME} is empty.\n\n"; continue; }
          notify_admin_MESSAGE="$notify_admin_MESSAGE\n---\n--- ${notify_admin_LOG_FNAME}\
:Last $notify_admin_NUM_LINES lines.\n---\n`eval tail -${notify_admin_NUM_LINES} $notify_admin_LOG_FNAME`\n"
        fi
      done
    fi

    #
    # Finally compose and send the message
    # ------------------------------------
    #

    [ -n "$notify_admin_COPY_TO" ] && notify_admin_MAILER_ARGS="$notify_admin_MAILER_ARGS \
-c $notify_admin_COPY_TO"
    {
      echo "Date:       `date`"
      echo "Host:       `hostname`"
      echo "OS:         `uname -sr`"
      echo "Uptime:     `uptime | sed 's/^[ ]*//;'`"
      echo "Command:    $0"
      [ -n "$notify_admin_ARGS" ] && echo "Args:       $notify_admin_ARGS"
      echo "---"
      echo "$notify_admin_SUBJECT"
      echo ""
      echo "$notify_admin_MESSAGE"
      echo "*** End ***"
    } | mailx -s "${notify_admin_STATUS}: $notify_admin_SUBJECT" \
            $notify_admin_MAILER_ARGS $notify_admin_ADMIN_MAIL
}

[1] Страница в интернет с описанием подсистемы SMF http://www.sun.com/bigadmin/content/selfheal/sdev_intro.html

Оригинал статьи: http://www.netup.ru/articles.php?n=14.

[ опубликовано 01/02/2006 ]

NetUP (info AT netup.ru) - Управление сервисами биллинговой системы в ОС Solaris 10   Версия для печати