Não está executando uma tarefa do cron quando a execução anterior não foi concluída

4

Como posso bloquear uma tarefa do cron quando a execução anterior não foi concluída. É uma tarefa do cron que está sendo executada a cada 5 minutos, mas às vezes precisa de mais de 5 minutos para ser executada.

Editar O script que é chamado, falha às vezes! Portanto, não é possível excluir o arquivo de bloqueio.

    
por powtac 09.11.2010 / 14:01

7 respostas

6

Use flock(1) :

NAME
       flock - manage locks from shell scripts

SYNOPSIS
       flock [options] <file> -c <command>
       flock [options] <directory> -c <command>
       flock [options] <file descriptor number>
[...]

Você pode bloqueá-lo ou sair imediatamente. A pré-existência (ou ausência) do arquivo de bloqueio não faz diferença. Ele cria o arquivo, se necessário, e usa uma chamada de sistema flock() para bloquear o arquivo. Este bloqueio é liberado automaticamente na morte do processo.

Por exemplo, no cron:

*/5 * * * * /usr/bin/flock /tmp/my.lock /usr/local/bin/myjob

Se os seus trabalhos nem sempre terminarem em 5 minutos, você pode considerar usar --timeout para que seus trabalhos não fiquem em fila:

flock --timeout=300

Ou use --nonblock para sair imediatamente - seria semelhante a --timeout=0

Se o seu script é um shell script, você pode usar alguns truques inteligentes de redirecionamento para usar o flock dentro do próprio script:

(
  flock -n 9 || exit 1
  # ... commands executed under lock ...
) 9>/var/lock/mylockfile            

Ou, o manual também sugere tornar seu script recursivo, colocando isso no topo (ele usa o próprio script como arquivo de bloqueio):

[ "${FLOCKER}" != "$0" ] && exec env FLOCKER="$0" flock -en "$0" "$0" "$@" || :

Veja a página flock(1) man para mais informações

    
por 02.07.2014 / 05:18
4

Os arquivos Pid são o caminho a seguir, no entanto, assim como os scripts init não desistem apenas quando vêem um arquivo pid, você deve verificar se o pid no arquivo ainda existe.

Algo assim faria o truque:

PIDFILE=/var/run/myscript.pid

if [ -e "$PIDFILE" ] ; then
    # our pidfile exists, let's make sure the process is still running though
    PID='/bin/cat "$PIDFILE"'
    if /bin/kill -0 "$PID" > /dev/null 2>&1 ; then
        # indeed it is, i'm outta here!
        /bin/echo 'The script is still running, forget it!'
        exit 0
    fi
 fi

 # create or update the pidfile
 /bin/echo "$$" > $PIDFILE

 ... do stuff ...

 /bin/rm -f "$PIDFILE"
    
por 09.11.2010 / 14:28
1

A verificação de arquivo pid ou lock pode falhar quando a tarefa cron falha ao limpar o arquivo após a saída. Eu vejo a melhor opção é verificar o processo em si, como:

ps -ef | grep script_name | grep -v grep | wc -l

Isso fornecerá o número de processos com o nome 'script_name'. Você pode verificar essa contagem no início da execução do seu script.

    
por 09.11.2010 / 14:10
0

Você não pode, cronjobs não vêm com essa funcionalidade. Coloque algo no seu script para verificá-lo ou crie um arquivo quando terminar e use algo como inotifywait para bloquear.

    
por 09.11.2010 / 14:04
0

Procure um arquivo em, por exemplo %código%. Se o arquivo for encontrado, saia. Caso contrário, crie o arquivo, execute sua rotina e remova o arquivo.

    
por 09.11.2010 / 14:04
0

Existem muitas maneiras. Popular é usar um arquivo de bloqueio.

1) Quando o script é iniciado, ele verifica se um arquivo de bloqueio (como /var/lock/powtac.loc ) já é apresentado.

2) Se existir, o script será anulado, assumindo que o script anterior ainda está em execução *).

3) Se não existir, o script cria o arquivo e continua a fazer o que for necessário.

4) Ao sair, o script exclui o arquivo de bloqueio.

*) Também seria possível verificar a lista de processos neste momento, procurar por correspondências para o seu cron job e, se encontradas, ver quando elas foram iniciadas. Se recentemente, suponha que eles ainda estejam em execução, se loooooooooo tempo atrás, presuma que eles estavam presos.

    
por 09.11.2010 / 14:05
-2

Eu não teria dois trabalhos agendados para ter um.

* * * * * /some/command && /some/other/command

Ele só será executado se o primeiro comando for concluído com êxito e somente depois de concluído.

(nota: se você precisar de alguns minutos após o uso sleep )

    
por 09.11.2010 / 14:07

Tags