Cron Script sendo executado várias vezes

Cron Script sendo executado várias vezes

Temos um script usado para sincronizar alguns diretórios com uma unidade de disco USB. Ele está configurado para ser executado uma vez por dia, mas geralmente leva mais tempo do que isso.

Para garantir que várias cópias do script não sejam executadas ao mesmo tempo, verificamos a lista de processos e se nosso script estiver presente, saímos imediatamente.

#!/bin/bash

#check if we are already running
running=$(ps aux | /usr/bin/grep -i "usb_sync" | /usr/bin/grep -v grep | /usr/bin/grep -c bash)
echo "usb_sync $running" >/opt/local/backup/usb_sync_log
#If we are, the quit
if [ $running -gt 1 ] ; then
  exit 0
fi

O problema é que essa verificação funciona bem ao ser executada via sudo e invocação manual por meio da CLI. No entanto, quando executado pelo cron, ele será iniciado de qualquer maneira. Eu tentei algumas variações diferentes, mas todas parecem funcionar.

Isso está no FreeNAS 11.2.

Responder1

Um pidarquivo é uma abordagem comum para evitar múltiplas execuções de um script. Pode ser usado assim:

#!/bin/bash

PIDFILE=/home/vagrant/forever.pid
if [ -f $PIDFILE ]
then
  PID=$(cat $PIDFILE)
  ps -p $PID > /dev/null 2>&1
  if [ $? -eq 0 ]
  then
    echo "Process already running"
    exit 1
  else
    ## Process not found assume not running
    echo $$ > $PIDFILE
    if [ $? -ne 0 ]
    then
      echo "Could not create PID file"
      exit 1
    fi
  fi
else
  echo $$ > $PIDFILE
  if [ $? -ne 0 ]
  then
    echo "Could not create PID file"
    exit 1
  fi
fi

sleep 25d
rm $PIDFILE

Onde sleep 25destá o comando real a ser executado. Eu recomendo ler issopostagem no blogpara uma explicação detalhada dos vários métodos para lidar com esse problema. O script acima foi retirado daí.

Os direitos de acesso do usuário para executar o script conforme definido no arquivo cron devem ser verificados. O script atual também pode simplesmente não conseguir identificar se o script já está em execução porque os direitos de acesso não são suficientes. De qualquer forma, usar um arquivo pid parece uma solução melhor e menos propensa a erros para lidar com esse problema.

Responder2

Pode ser feito muito mais fácil. Crie um arquivo de sinalização. No início do seu script, talvez use:

    ## Basic config
SCRIPTNAME=$(basename "$0")
RUNFILE="${SCRIPTNAME}.run"
# 25h in seconds adjust to your needs.
MAX_AGE=90000


    # check for running process
    if [ -f "$RUNFILE" ]; then
      echo "process still running - exit"
      if [ $(( $(date +%s) - $(date +%s --reference $RUNFILE) )) -gt ${MAX_AGE} ]; then
         rm $RUNFILE;
      else 
         exit
      fi
    fi
    touch $RUNFILE

<your code>

rm ${RUNFILE}

O conteúdo do runfile pode ser o PID do processo em execução. Seria mais fácil analisar se há um processo em execução.

Em vez de

touch ${RUNFILE}

usar

echo $$ >${RUNFILE}

informação relacionada