Cron脚本多次运行

Cron脚本多次运行

我们有一个脚本用于将一些目录同步到 USB 磁盘驱动器。它设置为每天运行一次,但通常需要更长时间。

为了确保脚本的多个副本不会同时运行,我们会检查进程列表,如果我们的脚本存在,我们会立即退出。

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

问题是,通过 sudo 和 CLI 手动调用时,此检查运行正常。但是,当通过 cron 运行时,它无论如何都会启动。我尝试了几种不同的变体,但它们似乎都可以运行。

这是在 FreeNAS 11.2 上。

答案1

文件pid是防止脚本多次执行的常用方法。可以这样使用:

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

实际要执行的命令在哪里sleep 25d。我建议阅读此博客文章深入了解处理此问题的各种方法。上面的脚本取自那里。

应检查 cron 文件中设置的用户执行脚本的访问权限。当前脚本也可能因为访问权限不足而无法识别脚本是否已在运行。无论如何,使用 pid 文件似乎是处理此问题的更好且更不容易出错的解决方案。

答案2

可以更轻松地完成。创建一个标志文件。在脚本的开头可以使用:

    ## 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}

runfile 的内容可能是正在运行的进程的 PID。这样可以更容易地分析是否有进程正在运行。

代替

touch ${RUNFILE}

使用

echo $$ >${RUNFILE}

相关内容