Eu preciso executar um script php como processo daemon (aguarde instruções e faça as coisas). O cron job não fará isso por mim, porque as ações precisam ser executadas assim que a instrução chegar. Eu sei que o PHP não é realmente a melhor opção para processos daemon devido a problemas de gerenciamento de memória, mas devido a várias razões, tenho que usar o PHP nesse caso. Me deparei com uma ferramenta da libslack chamada Daemon ( http://libslack.org/daemon ) que parece me ajudar a gerenciar processos daemon, mas não houve nenhuma atualização nos últimos 5 anos, por isso, gostaria de saber se você conhece algum outras alternativas adequadas ao meu caso. Qualquer informação será realmente apreciada.
154
Respostas:
Você pode iniciar seu script php na linha de comando (ou seja, bash) usando
nohup php myscript.php &
o
&
coloca seu processo em segundo plano.Edit:
Sim, existem algumas desvantagens, mas não é possível controlar? Isso está errado.
Um simples
kill processid
irá parar. E ainda é a melhor e mais simples solução.fonte
nohup
e&
faz a mesma coisa: desanexar o processo iniciado da atual intenção do shell. Por que eu preciso dos dois? Não posso simplesmente fazerphp myscript.php &
ounohup myscript.php
? Graçasnohup php myscript.php > myscript.log &
Outra opção é usar o Upstart . Ele foi originalmente desenvolvido para o Ubuntu (e vem com ele por padrão), mas destina-se a ser adequado para todas as distribuições do Linux.
Essa abordagem é semelhante ao Supervisord e daemontools , pois inicia automaticamente o daemon na inicialização do sistema e reaparece na conclusão do script.
Como configurá-lo:
Crie um novo arquivo de script em
/etc/init/myphpworker.conf
. Aqui está um exemplo:Iniciando e parando seu daemon:
Verifique se o seu daemon está em execução:
obrigado
Um grande obrigado a Kevin van Zonneveld , de onde aprendi essa técnica.
fonte
sudo service myphpworker start/stop/status
funciona apenas com serviços que/etc/init.d
não estão em serviços iniciantes. @ matt-sich parece ter descoberto a sintaxe correta. Outra opção é usar o Gearman ou o Resque, que permite o processamento em segundo plano e a desamonização.Com o novo systemd, você pode criar um serviço.
Você deve criar um arquivo ou um link simbólico em
/etc/systemd/system/
, por exemplo. myphpdaemon.service e coloque conteúdo como este, myphpdaemon será o nome do serviço:Você poderá iniciar, obter status, reiniciar e interromper os serviços usando o comando
systemctl <start|status|restart|stop|enable> myphpdaemon
O script PHP deve ter um tipo de "loop" para continuar em execução.
Exemplo de trabalho:
Se sua rotina PHP deve ser executada uma vez em um ciclo (como um resumo), você deve usar um script shell ou bash para ser chamado no arquivo de serviço systemd em vez do PHP diretamente, por exemplo:
Se você escolher essa opção, altere o KillMode para
mixed
para processos, bash (principal) e PHP (filho) sejam mortos.This method also is effective if you're facing a memory leak.
fonte
systemctl status <your_service_name> -l
saída, isso lhe dará uma pista do que está acontecendo.Se você puder - pegue uma cópia da Programação Avançada no ambiente UNIX . Todo o capítulo 13 é dedicado à programação de daemon. Os exemplos estão em C, mas toda a função que você precisa possui wrappers em PHP (basicamente as extensões pcntl e posix ).
Em poucas palavras - escrever um daemon (isso é possível apenas em sistemas operacionais baseados em * nix - o Windows usa serviços) é assim:
umask(0)
para evitar problemas de permissão.fork()
e faça com que o pai saia.setsid()
.SIGHUP
(geralmente isso é ignorado ou usado para sinalizar o daemon para recarregar sua configuração) eSIGTERM
(para dizer ao processo para sair normalmente).fork()
novamente e faça com que o pai saia.chdir()
.fclose()
stdin
,stdout
Estderr
e não escrever para eles. A maneira correta é redirecioná-los para um/dev/null
ou para um arquivo, mas não consegui encontrar uma maneira de fazê-lo no PHP. É possível quando você inicia o daemon para redirecioná-lo usando o shell (você terá que descobrir como fazer isso, não sei :).Além disso, como você está usando PHP, tenha cuidado com as referências cíclicas, pois o coletor de lixo do PHP, anterior ao PHP 5.3, não tem como coletar essas referências e o processo irá vazar na memória, até que eventualmente trava.
fonte
Eu corro um grande número de daemons PHP.
Concordo com você que o PHP não é a melhor (ou até boa) linguagem para fazer isso, mas os daemons compartilham código com os componentes voltados para a Web, portanto, no geral, é uma boa solução para nós.
Usamos daemontools para isso. É inteligente, limpo e confiável. De fato, nós o usamos para executar todos os nossos daemons.
Você pode verificar isso em http://cr.yp.to/daemontools.html .
EDIT: Uma lista rápida de recursos.
fonte
Você pode
nohup
como Henrik sugeriu.screen
e execute seu programa PHP como um processo regular dentro dele. Isso lhe dá mais controle do que usarnohup
.Eu recomendaria o método mais simples (tela na minha opinião) e, se desejar mais recursos ou funcionalidades, passe para métodos mais complexos.
fonte
Há mais de uma maneira de resolver esse problema.
Eu não sei os detalhes, mas talvez haja outra maneira de acionar o processo PHP. Por exemplo, se você precisar que o código seja executado com base em eventos em um banco de dados SQL, poderá configurar um gatilho para executar seu script. Isso é realmente fácil de fazer no PostgreSQL: http://www.postgresql.org/docs/current/static/external-pl.html .
Honestamente, acho que sua melhor aposta é criar um processo Damon usando nohup. nohup permite que o comando continue executando mesmo após o logout do usuário:
Existe, no entanto, um problema muito sério. Como você disse que o gerenciador de memória do PHP é um lixo completo, ele foi construído com a suposição de que um script está sendo executado apenas por alguns segundos e depois existe. Seu script PHP começará a usar GIGABYTES de memória após apenas alguns dias. Você DEVE TAMBÉM criar um script cron que seja executado a cada 12 ou talvez 24 horas que mata e gera novamente seu script php assim:
Mas e se o script estivesse no meio de um trabalho? Bem, kill -3 é uma interrupção, é o mesmo que fazer um ctrl + c na CLI. Seu script php pode capturar essa interrupção e sair normalmente usando a biblioteca pcntl do PHP: http://php.oregonstate.edu/manual/en/function.pcntl-signal.php
Aqui está um exemplo:
A idéia por trás do $ lock é que o script PHP pode abrir um arquivo com um fopen ("file", "w") ;. Somente um processo pode ter um bloqueio de gravação em um arquivo; portanto, usando isso, você pode garantir que apenas uma cópia do seu script PHP esteja em execução.
Boa sorte!
fonte
Kevin van Zonneveld escreveu um artigo detalhado muito bom sobre isso , em seu exemplo ele usa o
System_Daemon
pacote PEAR (data da última versão em 02/09/2009).fonte
Confira https://github.com/shaneharter/PHP-Daemon
Esta é uma biblioteca de daemon orientada a objetos. Ele possui suporte interno para itens como log e recuperação de erros, além de criar trabalhadores em segundo plano.
fonte
Recentemente, tive a necessidade de uma solução de plataforma cruzada (Windows, Mac e Linux) para o problema de executar scripts PHP como daemons. Resolvi o problema escrevendo minha própria solução baseada em C ++ e criando binários:
https://github.com/cubiclesoft/service-manager/
Suporte completo para Linux (via sysvinit), mas também serviços do Windows NT e Mac OSX launchd.
Se você só precisa do Linux, algumas das outras soluções apresentadas aqui funcionam bem o suficiente e, dependendo do sabor. Atualmente, também existe o Upstart e o systemd, que têm fallbacks para scripts sysvinit. Mas metade do ponto de usar o PHP é que ele é multiplataforma, por isso o código escrito na linguagem tem uma boa chance de trabalhar em todos os lugares como está. As deficiências começam a aparecer quando certos aspectos externos do nível do SO nativo entram em cena, como serviços do sistema, mas você terá esse problema com a maioria das linguagens de script.
Tentar captar sinais como alguém sugerido aqui na área de usuários do PHP não é uma boa idéia. Leia a documentação com
pcntl_signal()
atenção e você aprenderá rapidamente que o PHP lida com sinais usando alguns métodos bastante desagradáveis (especificamente, 'ticks') que produzem vários ciclos por algo raramente visto pelos processos (ou seja, sinais). A manipulação de sinais no PHP também não está disponível apenas nas plataformas POSIX e o suporte difere com base na versão do PHP. Inicialmente, parece uma solução decente, mas fica muito aquém de ser realmente útil.O PHP também está melhorando com relação a problemas de vazamento de memória à medida que o tempo avança. Você ainda precisa ter cuidado (o analisador DOM XML tende a vazar ainda), mas raramente vejo processos descontrolados hoje em dia e o rastreador de erros do PHP é bastante silencioso em comparação com os dias de outrora.
fonte
Como outros já mencionaram, executar o PHP como um daemon é bastante fácil e pode ser feito usando uma única linha de comando. Mas o problema real é mantê-lo funcionando e gerenciando-o. Eu já tive o mesmo problema há algum tempo e, embora já existam muitas soluções disponíveis, a maioria delas possui muitas dependências ou é difícil de usar e não é adequada para usos básicos. Eu escrevi um shell script que pode gerenciar qualquer processo / aplicativo, incluindo scripts cli PHP. Pode ser definido como um cronjob para iniciar o aplicativo e conterá o aplicativo e gerenciá-lo. Se for executado novamente, por exemplo, através do mesmo cronjob, ele verifica se o aplicativo está em execução ou não, se simplesmente sai e deixa sua instância anterior continuar gerenciando o aplicativo.
Fiz o upload para o github, fique à vontade para usá-lo: https://github.com/sinasalek/EasyDeamonizer
EasyDeamonizer
Simplesmente vigia seu aplicativo (iniciar, reiniciar, registrar, monitorar etc.). um script genérico para garantir que seu aplicativo continue sendo executado corretamente. Intencionalmente, ele usa o nome do processo em vez do arquivo pid / lock para evitar todos os seus efeitos colaterais e manter o script o mais simples e rápido possível, para que ele sempre funcione mesmo quando o EasyDaemonizer for reiniciado. Recursos
fonte
Estendendo a resposta de Emil Ivaov , você pode fazer o seguinte para fechar STDIN, STDOUT AND STDERROR em php
Basicamente, você fecha os fluxos padrão para que o PHP não tenha lugar para escrever. As seguintes
fopen
chamadas definirão o IO padrão para/dev/null
.Eu li isso no livro de Rob Aley - PHP além da web
fonte
Eu escrevi e implantei um simples php-daemon, o código está online aqui
https://github.com/jmullee/PhpUnixDaemon
Características: eliminação de privilégios, manipulação de sinal, registro
Usei-o em um manipulador de filas (caso de uso: aciona uma operação demorada a partir de uma página da web, sem fazer com que o php gerador de páginas aguarde, ou seja, inicie uma operação assíncrona) https://github.com/jmullee/PhpIPCMessageQueue
fonte
você pode verificar o pm2 aqui, http://pm2.keymetrics.io/
crie um arquivo ssh, como o worker.sh, inserido no seu script php com o qual você irá lidar.
worker.sh
início de daemon
Saúde, é isso.
fonte