я бегу небольшая многопользовательская карточная игра около 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
(и я добавил ночное задание cron в "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?
Просто удалите 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 минут, и он ничего не сделает, если он запущен, или перезапустит его, если он не работает.