www.Litecode.ru – Сборник рецептов для создания сайтов

Запуск демона на perl

ГлавнаяPerl → Perl-скрипт в режиме демона

Как то раз возникла необходимость запустить perl-скрипт в режиме демона. Зачем мне это было нужно — уже другая история, а вот как это происходило хочу поделиться.

Так как не особо люблю «изобретать велосипеды», первым делом решил «погуглить». Стоит отметить что примеров реализации нашлось не много, подавляющее большинство которых описывало прототип tcp-сервера с использованием IO::Socket или Socket, + ветвление с помощью fork() . Подобный вариант perl-демона не совсем подходил, и меня зацепило любопытство...
...здесь должно быть описание долгих часов поиска «момента истины», которые я опускаю... Решение оказалось довольно простым.

Шаг № 1. Код самого perl-демона.

#!/usr/bin/perl -w 
use strict;

if ( `ps afx | awk ’/exec-daemon$/ { print $1 }’`) {

   # чтобы не запустить еще один экземрляр.
   print "Usage: service exec-daemon {start|stop}
 exit...
";
   exit
   
}

# Тонкость в том, что когда запуск идет через init.d и демон
# еще не запущен, то pid процесса еще нет
# и данное условие не сработает.
# В случае прямого запуска данного скрипта pid процесса будет всегда,
# причем в лучшем случае собственный.

my $path = "/home/full/path/"; # не забудьте изменить на свой
$0 = "exec-daemon"; # даем имя процессу , для красоты
sub _log { 

   open (LOGF , ">>$path/error.log") or die $!; 
   print LOGF "[".(scalar localtime())."] -> ".( $_[0] ); 
   close LOGF; 

} 

# сам код 

while(1){  # делаем бесконечный цикл обязательно,
           # иначе отработает один раз и умрет

   _log("Hello!"); # например такое действие для наглядности

    sleep (5); # каждые 5 секунд

}

Данный пример можно вполне взять за болванку для Ваших целей. Плюс в том что выполнять код можно хоть каждую секунду, в отличии от cron. Запускать можно в ручную, только не забудьте о правах на исполнение и добавить & в консоли, что бы демон запустился в фоновом режиме. Например: /home/full/path/exec-daemon &
Едем дальше...

Шаг № 2. Автозапуск perl-демона при загрузке системы.

Здесь все стандартно и просто — /etc/rc.d Отмечу что эксперименты проводились на Ubuntu 10.04, и возможно некоторые элементы могут различаться. В папку /etc/init.d/ кладем shell-скрипт для запуска нашего демона:

#!/bin/sh -e 
### BEGIN INIT INFO 
# Provides: exec-daemon 
# Required-Start: $local_fs $remote_fs $network $syslog 
# Required-Stop: $local_fs $remote_fs $network $syslog 
# Default-Start: 2 3 4 5 
# Default-Stop: 0 1 6 
# X-Interactive: true 
# Short-Description: Start/stop exec-daemon 
### END INIT INFO 


ENV="env -i LANG=C PATH=/usr/bin/perl:/usr/bin:/bin" 
. /lib/lsb/init-functions 

set -e 

PID=`ps afx | awk '/exec-daemon$/ { print $1 }'` 

case "$1" in 
start) 
if [ $PID ]; then 

echo "ERROR: Another exec-daemon already run! PID:" $PID 

break; 

else 

echo "Starting exec-daemon ... "; 
'/home/full/path/exec-daemon' start & 
echo "OK" 

fi 

;; 
stop) 

echo "Stoping exec-daemon ... "; 
pkill -TERM exec-daemon || true 
echo "OK" 
;; 


*) 
N=/etc/init.d/exec-daemon 

echo "Usage: $N {start|stop}" >&2 
exit 1 
;; 
esac 

exit 0

Обратите внимание сюда: PID=`ps afx | awk ’/exec-daemon$/ { print $1 }’` Я пошел таким путем, чтобы при запуске perl-демона не смотреть pid и lock — файлы. т. е. Смотрим сразу в процессах, и далее если есть pid ругаемся, или запускаем.

Далее создаем символические ссылки в папки rc0.d — rcS.d, опционально куда пожелаете, но минимум в rc3.d. Здесь правда есть нюанс: название ссылки должно начинаться с S или K, что значит запуск или остановка соответственно; после должно идти число от 0 до 100, которое означает порядок запуска вашего процесса. А уж потом название вашего shell-скрипта.

Например @S91exec-daemon, (для новичков: собака появиться автоматически при создании символической ссылки. Ctrl + x + s) Все! Перегружаемся, делаем в консоли ps afx и ищем там нашего демона.