Reiniciando um script Perl (daemon de socket) do / etc / inittab

2

Eu corro um pequeno jogo de cartas multijogador com cerca de 500 usuários nos horários de pico:

OclienteestáemFlasheoservidorestáemPerl.

OservidorPerlseconectaàporta8080,ouseja,apenas1instânciadelepodeseriniciada(detalhesimportantes).

OservidorPerlpoll()sTCP-socketseforksapenasumavez-nainicializaçãochamandoestemétodo:

subdaemonize{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;

Ele roda no CentOS 5.6 Linux / 64 bits, PostgreSQL 8.4.8 e Perl 5.8.8.

Como meu orçamento é pequeno e já tive problemas suficientes, quero usar o mínimo possível de software adicional - para poder alterar os hosters ou reinstalar rapidamente o meu servidor barato. É por isso que eu, por exemplo, apenas faço o log em /tmp/pref.txt ao invés de instalar o syslog-ng. E é por isso que eu gostaria de usar o / etc / inittab para reiniciar meu daemon do Perl .

Meu daemon Perl roda praticamente estável, mas aprox. uma vez por semana, pode falhar com um

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

Como estou cansado de reiniciar o servidor manualmente, tentei adicioná-lo ao / etc / inittab:

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

(e eu adicionei um cronjob noturno para "pkill pref.pl" na esperança de atualizar o perl desta forma).

Infelizmente, isso não funciona como esperado - nas / var / log / messages, vejo que o script está sendo iniciado de novo e de novo:

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

O que estou fazendo de errado aqui? Eu estava esperando poder usar o / etc / inittab aqui, porque eu me lembro de usá-lo para uma situação semelhante no trabalho há alguns anos (também com um daemon Perl) e funcionou bem então ...

Obrigado! Alex

ATUALIZAÇÃO:

Meu jogo não está falhando, o interpretador perl faz (mas não frequentemente, uma vez por semana).

Minha pergunta é sobre como executar um daemon Perl (ou seja, um script Perl que se bifurca uma vez no início e depois se liga a uma porta TCP) do / etc / inittab?

    
por Alexander Farber 02.06.2011 / 21:41

2 respostas

1

Basta remover o fork () do código. Até este ponto, você escreveu uma parte do código que deseja remover do console e executar em segundo plano. No entanto, quando os processos são executados no inittab, eles precisam permanecer conectados. Se você remover o fork (), ele permanecerá conectado ao init e o init poderá monitorar / iniciar / parar / reiniciar corretamente

    
por 02.06.2011 / 22:24
0

Eu não posso falar com a sua solução inittab, espero que outra pessoa possa, mas eu quero sugerir que você olhe para "File :: Pid" como algo para adicionar ao seu script - após a chamada daemonize (isso é importante - seu ID de processo muda depois de um fork).

use File::Pid;

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

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

Isso lhe dá algumas coisas - uma que garante que você não execute duas cópias ao mesmo tempo (o que você disse que era um grande problema) e também permitiria que você ligasse para esse programa com segurança sempre que quisesse fornecer um manutenção simples. Basta chamar seu código do cron a cada 10 minutos, e ele não fará nada se estiver em execução ou será reiniciado se estiver inativo.

    
por 02.06.2011 / 22:10