Cron Script ejecutándose varias veces

Cron Script ejecutándose varias veces

Tenemos un script que se utiliza para sincronizar algunos directorios con una unidad de disco USB. Está configurado para ejecutarse una vez al día, pero a menudo tarda más.

Para asegurarnos de que no se ejecuten varias copias del script al mismo tiempo, verificamos la lista de procesos y, si nuestro script está presente, salimos inmediatamente.

#!/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

El problema es que esta verificación funciona bien cuando se ejecuta mediante sudo y la invocación manual a través de la CLI. Sin embargo, cuando se ejecuta a través de cron, se iniciará independientemente. He probado un par de variaciones diferentes pero todas parecen funcionar.

Esto está en FreeNAS 11.2.

Respuesta1

Un pidarchivo es un enfoque común para evitar ejecuciones múltiples de un script. Se puede utilizar así:

#!/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

¿Dónde sleep 25dse ejecutará el comando real? recomiendo leer estoentrada en el blogpara obtener una explicación detallada de los diversos métodos para manejar este problema. El guión de arriba está tomado de allí.

Se deben verificar los derechos de acceso del usuario para ejecutar el script tal como se establece en el archivo cron. El script actual también podría no identificar si ya se está ejecutando porque los derechos de acceso no son suficientes. De cualquier manera, usar un archivo pid parece una solución mejor y menos propensa a errores para manejar este problema.

Respuesta2

Se puede hacer mucho más fácil. Crea un archivo de bandera. Al comienzo de su script tal vez 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}

El contenido del archivo de ejecución podría ser el PID del proceso en ejecución. Sería más fácil analizar si hay un proceso en ejecución.

En lugar de

touch ${RUNFILE}

usar

echo $$ >${RUNFILE}

información relacionada