Перезапуск Perl-скрипта (демон сокета) из /etc/inittab

Я запускаю небольшую многопользовательскую карточную игру с около 500 пользователями в часы пик:

Скриншот

Клиент находится во Flash, а сервер - в Perl.

Сервер Perl связывается с портом 8080, т.е. может быть запущен только 1 его экземпляр (важная деталь).

Сервер Perl опрашивает TCP-сокеты и разветвляется только один раз - при запуске, вызывая этот метод:

sub daemonize {
    die "Can not fork: $!\n" unless defined (my $child = fork());
    # the parent should die
    exit 0 if $child;

    setsid();
    open(STDIN, '</dev/null');
    open(STDOUT, '>/tmp/pref.txt');
    open(STDERR, '>&STDOUT');
    chdir('/');
    umask(0);
}
....
$tcpSocket = IO::Socket::INET->new(Proto     => 'tcp',
                                   LocalPort => 8080,
                                   Listen    => SOMAXCONN,
                                   ReuseAddr => 1,
                                   );
die "Can not create listening TCP socket: $!\n"
        unless defined $tcpSocket;

Он работает на CentOS 5.6 Linux / 64 bit, PostgreSQL 8.4.8 и Perl 5.8.8.

Поскольку у меня небольшой бюджет и у меня уже было достаточно проблем, я хочу использовать как можно меньше дополнительного программного обеспечения, чтобы я мог сменить хостеров или быстро переустановить мой дешевый сервер. Вот почему я, например, просто захожу в /tmp/pref.txt вместо установки syslog-ng. И именно поэтому я хотел бы использовать / etc / inittab для перезапуска моего демона Perl.

Мой Perl-демон работает в основном стабильно, но ок. один раз в неделю это может привести к сбою

May 29 11:06:46 myhost kernel: pref.pl[3113]: segfault at 00007fffa21e6fd8 rip 0000003cce274460 rsp 00007fffa21e6fd0 error 6

Поскольку я устал от перезапуска сервера вручную, я попытался добавить его в / etc / inittab:

pref:3:respawn:/bin/su -c '/usr/local/pref/pref.pl' nobody

(и я добавил ночной кронджоб в "pkill pref.pl" в надежде обновить perl таким образом).

К сожалению, это не работает должным образом - в / var / log / messages я вижу, что скрипт запускается снова и снова:

Jun  2 18:55:56 myhost init: Id "pref" respawning too fast: disabled for 5 minutes
Jun  2 19:00:58 myhost init: Id "pref" respawning too fast: disabled for 5 minutes
Jun  2 19:06:02 myhost init: Id "pref" respawning too fast: disabled for 5 minutes

Что я здесь не так делаю? Я надеялся, что смогу использовать / etc / inittab здесь, потому что я помню, как использовал его для аналогичной ситуации на работе несколько лет назад (также с демоном Perl), и тогда он работал хорошо...

Спасибо! Alex

ОБНОВИТЬ:

Моя игра не падает, интерпретатор Perl делает (но не часто, один раз в неделю).

Мой вопрос о том, как запустить демон Perl (т.е. скрипт Perl, который сначала разветвляется, а затем привязывается к порту TCP) из /etc/inittab?

2 ответа

Решение

Просто удалите fork() из кода. К этому моменту вы написали кусок кода, который хотите отключить от консоли и запустить в фоновом режиме. Однако, когда процессы запускаются из inittab, они должны оставаться подключенными. Если вы удалите fork(), он останется подключенным к init, и init сможет правильно контролировать / запускать / останавливать / перезапускать

Я не могу поговорить с вашим решением inittab, надеюсь, кто-то другой может, но я хочу предложить вам взглянуть на "File::Pid" как на то, что можно добавить в ваш скрипт - после вызова daemonize (это важно - идентификатор вашего процесса) меняется после развилки).

use File::Pid;

my $pidfile = File::Pid->new({
                            file => '/var/run/myprogram.pid',
                            pid => $$,
                            });

if ( my $num = $pidfile->running ) {
    exit;
}
$pidfile->write;

Это дает вам пару вещей - одно гарантирует, что вы не запускаете две его копии одновременно (что, как вы сказали, было большим делом), и это также позволит вам безопасно вызывать эту программу всякий раз, когда вы захотите предоставить простой keepalive. Просто вызывайте ваш код из cron каждые 10 минут, и он ничего не сделает, если он работает, или перезапустите его, если он не работает.

Другие вопросы по тегам