Minutamente cron, assegurando apenas uma única instância

9

Existe uma maneira de executar um script a cada minuto (ou 2, ou 5, etc), mas somente se ele ainda não estiver em execução?

Temos um conjunto de scripts que precisam ser executados a cada minuto. Às vezes eles podem começar e terminar em um segundo, outras vezes podem durar 5 minutos.

Nosso modo atual de evitar execuções simultâneas é definir um sinalizador is_running em cada script e sair, se ainda estiver habilitado. Mas isso é um pouco não confiável (isto é, erros fatais podem fazer com que o sinalizador permaneça ativado mesmo depois que o script é interrompido).

Poderíamos escrever nosso próprio gerenciador, mas estou imaginando se existe uma solução mais moderna que já exista.

    
por chroder 06.04.2010 / 18:12

5 respostas

8

a melhor maneira é usar flock em vez de um pidfile. verifique a manpage: flock (1) . A vantagem é que, não importa como um processo termine / morra, a fechadura desaparece.

    
por 06.04.2010 / 18:19
3

Eu tenderia a concordar com a resposta do arquivo pid da Warner. No entanto, o seguinte recurso do Anacron faz isso?

-s
    Serialize execution of jobs. Anacron will not start a new job before the previous one finished. 

Eu mesmo não testei, não acho a documentação do anacron completa o suficiente ...

Se você quer ser particularmente preguiçoso ;-) Você pode apenas fazer o script sair se o greping através da saída ps retornar o processo como em execução. Mas um arquivo lock / pid é melhor.

    
por 06.04.2010 / 18:20
1

Essa é a solução adequada para essa abordagem. Normalmente, um arquivo pid seria usado e um teste de pid seria feito contra o processo para garantir sua execução. Se obsoleto, o arquivo de bloqueio seria removido e o processo seria executado de qualquer maneira.

Qualquer inteligência adicional seria tipicamente escrita no próprio software, como um daemon, ao invés de rodar no cron.

    
por 06.04.2010 / 18:15
1

Se os seus scripts forem codificados em um idioma que suporte o flock (2) syscall, você também poderá agrupar () um arquivo de bloqueio com uma chamada de função. Exemplo:

Se você está preso ao Bash ou outra linguagem de script que não suporta isso, a solução já proposta com flock (1 ) também está bem.

P.S. Em qualquer caso, você deve criar um arquivo de bloqueio separado apenas uma vez (se já não existir) e nunca excluí-lo. O diretório "/ var / lock" é um bom lugar para esses arquivos.

    
por 06.04.2010 / 20:23
0

Esta é uma solução se o seu script é executado em python (ou você poderia criar um comando python para executar antes do próximo comando) - Eu encontrei este problema exato na semana passada, e embora eu tenha encontrado algumas boas soluções, decidi faça um pacote python muito simples e limpo e carregue-o no PyPI. Você certamente pode bloquear __file__ para não ter que pensar em fornecer um nome de recurso personalizado para bloquear.

Instale com: pip install quicklock

Usar é extremamente simples:

[nate@Nates-MacBook-Pro-3 ~/live] python
Python 2.7.6 (default, Sep  9 2014, 15:04:36)
[GCC 4.2.1 Compatible Apple LLVM 6.0 (clang-600.0.39)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from quicklock import singleton
>>> # Let's create a lock so that only one instance of a script will run
...
>>> singleton('hello world')
>>>
>>> # Let's try to do that again, this should fail
...
>>> singleton('hello world')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/nate/live/gallery/env/lib/python2.7/site-packages/quicklock/quicklock.py", line 47, in singleton
    raise RuntimeError('Resource <{}> is currently locked by <Process {}: "{}">'.format(resource, other_process.pid, other_process.name()))
RuntimeError: Resource <hello world> is currently locked by <Process 24801: "python">
>>>
>>> # But if we quit this process, we release the lock automatically
...
>>> ^D
[nate@Nates-MacBook-Pro-3 ~/live] python
Python 2.7.6 (default, Sep  9 2014, 15:04:36)
[GCC 4.2.1 Compatible Apple LLVM 6.0 (clang-600.0.39)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from quicklock import singleton
>>> singleton('hello world')
>>>
>>> # No exception was thrown, we own 'hello world'!

Dê uma olhada: link

    
por 28.01.2015 / 08:01

Tags