Como posso executar um script do cron apenas uma vez por vez?

2

Eu gostaria de executar um cron job. Agendar é fácil e funciona.

Meu problema é que não sei como ter apenas uma versão de si mesmo por vez.

Alguma idéia?

G-Man

    
por GeoffreyF67 14.10.2010 / 22:19

6 respostas

10

Minhas desculpas para embobo, mas eu copiei seu roteiro e o modifiquei para eliminar a condição de corrida que notei em meu comentário à sua resposta:

#!/bin/sh
LOCKDIR=/var/run/myprog.lock
mkdir --mode=700 $LOCKDIR || exit 0
trap "{ rm -rf $LOCKDIR ; exit 0; }" EXIT
# do stuff

Basicamente, estamos contando com o fato de que a criação de diretórios é atômica, de modo que apenas uma cópia desse script seja executada simultaneamente pode criar com êxito $LOCKDIR . Provavelmente, é melhor certificar-se de que $LOCKDIR esteja em uma unidade local, não em um disco NFS ou em uma montagem Samba, etc.

    
por 14.10.2010 / 23:04
4

Você pode usar um arquivo de bloqueio. Exemplo de código de shell:

#!/bin/sh
LOCKFILE=/var/run/myprog.pid
[ -f $LOCKFILE ] && exit 0
trap "{ rm -f $LOCKFILE ; exit 0; }" EXIT
echo "$$" > $LOCKFILE
# do stuff

É importante garantir que o arquivo de bloqueio seja removido em qualquer tipo de saída (normal ou anormal). Isso é o que o comando trap faz.

Você poderia torná-lo mais sofisticado fazendo mais se o arquivo de bloqueio existir. Por exemplo, obtenha o pid do arquivo e veja se ele está sendo executado.

    
por 14.10.2010 / 22:33
2

Basta que seu script toque em um arquivo quando ele for iniciado e exclua esse arquivo quando ele for concluído. Então, dentro do script, você pode verificar a existência desse arquivo antes de fazer qualquer coisa.

No pseudocódigo:

if (!exists(/var/run/filename))
{
    touch /var/run/filename;
    do stuff;
    rm /var/run/filename;
}
    
por 14.10.2010 / 22:31
1

Você pode fazer o acima onde você cria um arquivo de bloqueio ou diretório. Eu pessoalmente abro uma conexão de soquete para alguma porta alta. Isso garante que, mesmo se o aplicativo travar, o soquete será fechado. Com um arquivo de bloqueio, o arquivo pode continuar e seu script não será executado até que você o remova manualmente.

Na minha experiência, isso provou ser mais confiável.

    
por 18.10.2010 / 23:40
1

Existe um binário "lockfile" instalado na maioria dos sistemas que você pode usar para evitar entrar no jogo de controle de scripts do bash. No RHEL / CentOS / Fedora, é parte do pacote procmail.

Então você poderia colocar algo como: lockfile /var/lock/mycron.lock && /usr/local/bin/mycron && rm -f /var/lock/mycron.lock

Há mais opções na página do manual, você pode configurá-lo para aguardar algum tempo, limpar depois de si mesmo, etc.

    
por 19.10.2010 / 00:25
0

Parece ter sucesso com o seguinte script de chamada:

#!/bin/zsh
RED_="3[31m"
BLUE_="3[34m"
BLACK_="3[0m"
if [ $# -lt 1 ]; then
 echo "$0: Invoke a program/script only once at a time"
 echo "Syntax: $0 <program/script with parameters>"
else
 if ps -Alf | grep "$*" | grep -v grep | grep -v $0 >/dev/null; then
  echo "$BLUE_\"$@\"$RED_ runs already. I don't invoke it.$BLACK_"
 else
  echo "${RED_}I invoke: $BLUE_$@$BLACK_"
  $@
 fi
fi
    
por 26.10.2014 / 16:14