Programei um trabalho cron para ser executado a cada minuto, mas às vezes o script leva mais de um minuto para terminar e não quero que os trabalhos comecem a "empilhar" um sobre o outro. Acho que esse é um problema de simultaneidade - ou seja, a execução do script precisa ser mutuamente exclusiva.
Para resolver o problema, fiz o script procurar a existência de um arquivo específico (" lockfile.txt ") e sair se ele existir ou se não existir touch
. Mas este é um semáforo bastante ruim! Existe uma prática recomendada que eu deva conhecer? Eu deveria ter escrito um daemon?
fonte
flock -n file command
eflock -n file -c command
?-c
executa o comando especificado por meio de um shell (conforme a página de manual), enquanto a forma "nua" (não-c
) é apenasexec
o comando fornecido . Colocar algo no shell permite que você faça coisas do tipo shell (como executar vários comandos separados por;
ou&&
), mas também abre para ataques de expansão do shell se você estiver usando entrada não confiável.frequent_cron_job
comando (hipotético) que tentou mostrar que ele estava sendo executado a cada minuto. Eu o removi, uma vez que não acrescentou nada útil e causou confusão (sua, se mais ninguém estiver ao longo dos anos).A melhor maneira de usar shell é usar o rebanho (1)
fonte
99
e>
por isso é99> /...
Na verdade,
flock -n
pode ser usado em vez delckdo
*, então você estará usando o código dos desenvolvedores do kernel.Com base no exemplo de womble , você escreveria algo como:
BTW, olhando para o código, todos
flock
,lockrun
elckdo
fazer exatamente a mesma coisa, por isso é apenas uma questão do que é mais prontamente disponível para você.fonte
Você pode usar um arquivo de bloqueio. Crie esse arquivo quando o script iniciar e exclua-o quando terminar. O script, antes de executar sua rotina principal, deve verificar se o arquivo de bloqueio existe e prosseguir de acordo.
Os arquivos de bloqueio são usados por initscripts e por muitos outros aplicativos e utilitários nos sistemas Unix.
fonte
Você não especificou se deseja que o script aguarde a execução anterior ou não. Em "Não quero que os trabalhos comecem a se" empilhar ", acho que você está sugerindo que deseja que o script saia se já estiver em execução,
Portanto, se você não quiser depender do lckdo ou similar, faça o seguinte:
fonte
Isso também pode ser um sinal de que você está fazendo a coisa errada. Se seus trabalhos são executados de maneira muito próxima e frequente, talvez você deva desconcentrá-lo e torná-lo um programa no estilo daemon.
fonte
Seu daemon cron não deve chamar trabalhos se as instâncias anteriores deles ainda estiverem em execução. Eu sou o desenvolvedor de um cron daemon dcron e tentamos especificamente impedir isso. Não sei como o Vixie cron ou outros daemons lidam com isso.
fonte
Eu recomendaria usar o comando executar um - muito mais simples do que lidar com os bloqueios. Dos documentos:
run-one é um script de wrapper que executa não mais que uma instância exclusiva de algum comando com um conjunto exclusivo de argumentos. Isso geralmente é útil com cronjobs, quando você não deseja mais de uma cópia em execução por vez.
O run-this-one é exatamente como o run-one, exceto que ele usará o pgrep e o kill para encontrar e eliminar todos os processos em execução pertencentes ao usuário e correspondentes aos comandos e argumentos de destino. Observe que executar este bloqueará ao tentar eliminar os processos correspondentes, até que todos os processos correspondentes estejam mortos.
A execução um funciona constantemente exatamente como a execução um, exceto que ele reaparece "COMMAND [ARGS]" sempre que o COMMAND sai (zero ou diferente de zero).
keep-one-running é um alias para run-one-constantemente.
executar um até o sucesso opera exatamente como executar um constantemente, exceto que ele reaparece "COMMAND [ARGS]" até que o COMMAND saia com êxito (ou seja, sai zero).
executar um até a falha opera exatamente como executar um constantemente, exceto que ele reaparece "COMMAND [ARGS]" até que COMMAND saia com falha (ou seja, sai diferente de zero).
fonte
Agora que o systemd foi lançado, existe outro mecanismo de agendamento nos sistemas Linux:
UMA
systemd.timer
Em
/etc/systemd/system/myjob.service
ou~/.config/systemd/user/myjob.service
:Em
/etc/systemd/system/myjob.timer
ou~/.config/systemd/user/myjob.timer
:Se a unidade de serviço já estiver ativando quando o próximo timer for ativado, outra instância do serviço não será iniciada.
Uma alternativa, que inicia o trabalho uma vez na inicialização e um minuto após a conclusão de cada execução:
fonte
Eu criei um jar para resolver esse problema, como crons duplicados em execução podem ser java ou cron cron. Apenas passe o nome do cron em Duplicates.CloseSessions ("Demo.jar"), isso pesquisará e eliminará o pid existente para esse cron, exceto o atual. Eu implementei o método para fazer isso. Pronome da string = ManagementFactory.getRuntimeMXBean (). GetName (); String pid = proname.split ("@") [0]; System.out.println ("PID atual:" + pid);
E então mate killid string com o comando shell novamente
fonte
A resposta de @Philip Reynolds começará a executar o código após o tempo de espera de 5s de qualquer maneira, sem obter o bloqueio. Seguir Flock não parece estar funcionando . Modifiquei a resposta de @Philip Reynolds para
para que o código nunca seja executado simultaneamente. Em vez disso, após os 5 segundos, aguarde o processo sairá com 1 se não tiver o bloqueio até então.
fonte