Eu tenho um cronjob que executa PHP em um arquivo wordpress cron.php. É usado principalmente para agendar postagens e acredito que pode atualizar o cache.
Eu executo o cron job a cada minuto. Eu verifiquei o ps com frequência e vejo DUAS instâncias do PHP executando cron.php. Agora, isso é desnecessário porque a execução de uma instância fará tudo o que for necessário. Eu tenho outro trabalho que verifica a memória RAM e, às vezes, duas instâncias a desativam (espero uma grande quantidade de memória RAM disponível o tempo todo, posso reduzi-la, mas não quero). Não acredito que um trabalho possa levar mais de um minuto (embora possa).
Como executo um trabalho, mas não se o processo já existir? Eu não acho que o próprio código PHP possa verificar, a menos que conecte/use o banco de dados? Existe um comando cron que eu possa usar? Não quero matar uma instância se for> 1 minuto. Apenas não gere novos.
Responder1
Aqui está uma solução simples de script bash; você provavelmente pode fazer o mesmo no script cron.php. Na verdade, ele verifica processos que demoram muito; para um sistema automatizado, esta é provavelmente uma boa ideia.
#!/bin/bash
# Exit if process is already running
if test -e /tmp/wordpress-job.pid; then
# Check if the pid that was stored in /tmp/wordpress-job.pid does exist
if ps ax -o pid= | grep $(cat /tmp/wordpress-job.pid ) &> /dev/null; then
exit 0
fi
fi
# Create the file that marks this process as running
echo $$ > /tmp/wordpress-job.pid
# Some extra security check to prevent the pid file
# to survive.
trap "rm -f /tmp/wordpress-job.pid" EXIT TERM INT HUP
# Start the long-running process in the background
sleep 3600 & # long-running process
# Sleep some time before trying to kill that process
sleep 300
# Kill job if it takes longer than it should
kill %1
# Delete the file that marks this process as running
rm -f /tmp/wordpress-job.pid
Você deve substituir o "sleep 3600" pela sua linha de comando do php e alterar o 300 abaixo para o tempo máximo que seu script deve ter permissão para ser executado.
Responder2
Faça sua entrada crontab executar isto:
if mv /var/run/my-php-job.pending /var/run/my-php-job.running 2>/dev/null; then
echo $$ >|/var/run/my-php-job.running # optional
… # run the job
: >|/var/run/my-php-job.running # optional
mv /var/run/my-php-job.running /var/run/my-php-job.pending
fi
Coloque isso em uma @reboot
entrada do crontab:
rm -f /var/run/my-php-job.running
touch /var/run/my-php-job.pending
O nome do arquivo serve como bloqueio. Enquanto estiver .running
, há um trabalho em execução e o próximo trabalho não será iniciado. Quando for .pending
, o trabalho em execução será iniciado e alternado para .running
.
Se você incluir as linhas opcionais, o ID do processo do shell será gravado no .running
arquivo, para fins de investigação se um trabalho travar. Um arquivo de log tornaria isso redundante.
Se o shell que executa o trabalho travar (o que é improvável, e só corre o risco de acontecer se alguém o matar deliberadamente ou estiver com pouca memória, o arquivo de bloqueio ficará preso em .running
. (Se o trabalho em si travar, não há problema). Você pode detectar a morte súbita de um script anterior, mas é significativamente mais difícil.
Responder3
Existem utilitários especiais para evitar execuções paralelas: rebanho no util-linux, lockf em sistemas BSD, shlock no NetBSD e com pacotes INN e cnews.
No caso mais provável (Linux), chame algo semelhante a:
flock -w 60 /somedir/lockfile cron.php
As receitas em outras respostas são alternativas de rebanhos caseiros e são úteis apenas em caso de ausência dessa ferramenta.
OTOH, você pode lidar diretamente com esse bloqueio em seu programa, mas deve repetir todos os detalhes com cuidado, caso contrário, poderá criar uma condição de corrida.