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}

運行檔案的內容可以是正在運行的進程的PID。有進程正在運行會更容易分析。

代替

touch ${RUNFILE}

使用

echo $$ >${RUNFILE}

相關內容