Centos

為什麼備份腳本會因 cron 而失敗?

  • February 23, 2017

所以我正在對數據庫進行自動備份。備份腳本在我手動執行以及 Cron 執行計劃的每小時和每日備份時都可以正常工作。但是,每周和每月備份會失敗。

我(顯然)不確定,但我想我的問題出在 cron 配置上。也許是因為腳本在午夜執行多次而發生衝突?我不確定這是否可能,但如果是這樣,我將不勝感激有關微調我的 crontab 的說明。

我的 crontab:

# *  *  *  *  * user-name  command to be executed
 00 *  *  *  *   /data/backup.sh -h  #hourly
 00 00 *  *  *   /data/backup.sh -d  #daily
 00 00 *  *  6   /data/backup.sh -w  #weekly
 00 00 1  *  *   /data/backup.sh -m  #monthly

編輯:我更新了我的 crontab 以交錯分鐘,但它仍然不起作用:

# *  *  *  *  * user-name  command to be executed
 00 *  *  *  *   /data/backup.sh -h  #hourly
 05 00 *  *  *   /data/backup.sh -d  #daily
 10 00 *  *  6   /data/backup.sh -w  #weekly
 15 00 1  *  *   /data/backup.sh -m  #monthly

我通過以下命令訪問這些:

sudo crontab -u my_user_group_name -e

linux版本:

$ cat /proc/version 
Linux version 3.10.0-514.6.1.el7.x86_64 (builder@kbuilder.dev.centos.org) (gcc version 4.8.5 20150623 (Red Hat 4.8.5-11) (GCC) ) #1 SMP Wed Jan 18 13:06:36 UTC 2017

當作為手動 shell 腳本執行時,帶有任何標誌(-h、-d、-w、-m)的備份腳本本身就可以正常工作。它可以正常工作。它是一個 Wordpress 備份腳本,使用wp-cli,它本質上是對 MariaDB 數據庫進行序列化。為了完整起見,我在這個問題的末尾包含了腳本。

我已經仔細檢查了這個答案中的一般 cron 故障排除建議,但我沒有看到任何適用於我的問題的內容:

  • 我認為問題不在於備份腳本本身,因為該問題僅在 cron 執行期間發生,而不是在它直接在 shell 中執行時發生。很高興有人證明我錯了。
  • 我認為問題不在於更廣泛的環境,而是與 cron 配置本身(上圖)有關,因為該問題僅在某些 cron 執行期間發生,但其他執行成功。例如,Crontab 沒有命名錯誤,它具有正確的權限等。
  • cron 的答案沒有說明 cron 執行的頻率、執行之間的衝突或我認為可能是問題背後的其他動態。

以下是相關備份目錄的權限(在. 中/data/backup/。如您所見,每小時和每週目錄具有相同的權限。

drwxr-xr-x. 2 libsys  libsys   4096 Feb 20 00:05 daily
drwxrwxr-x. 2 root    backup   4096 Feb 20 10:00 hourly
-rw-rw-r--. 1 root    backup  35644 Feb 20 10:00 log.txt
drwxrwxr-x. 2 root    backup   4096 Feb 13 11:23 manual
drwxrwxr-x. 2 aberry3 aberry3  4096 Feb  6 10:36 monthly
drwxrwxr-x. 2 aberry3 aberry3  4096 Feb  6 10:36 weekly

我只是注意到每日權限沒有組寫入;我會解決這個問題並在一周後回來查看。然而,這可能是一個紅鯡魚。我的問題不在於每日備份,它工作正常:只有每周和每月備份不會發生。

這是備份腳本:

#!/bin/bash

# Usage
# This script will make a backup of the WordPress database, into the
# defined backup directory, "/data/backups".
# Options are -hdwm, for "hourly", "daily", "weekly", "monthly"; these
# simply put the backups into different subdirectories.  Running the script
# without options creates four backups, one in each directory.
# The script also "cleans up" the directories afterward.

# constants
WP_DIR=/var/www/wordpress/docroot
DATA_DIR=/data/backups
LOG=$DATA_DIR/log.txt

# vars
TIMESTAMP=$(date +%Y-%m-%d.%H-%M-%S)

# run all commands from WP root directory
cd $WP_DIR

# the meat of the backup script
backup () { # arguments: "hourly", "daily", "weekly", "monthly", "manual"
 INTERVAL=$1
 BACKUP_DIR=$DATA_DIR/$INTERVAL

 # create directory hierarchy if not exists
 mkdir -p $BACKUP_DIR

 # create backup
 FILENAME=$(printf "%s/wp-mariadb-%s.sql" "$BACKUP_DIR" "$TIMESTAMP")
 /usr/local/bin/wp db export $FILENAME

 # make sure backup happened
 if [ -s $FILENAME ]
 then
     echo "√   backup OK   $TIMESTAMP $INTERVAL" >> $LOG
 else
     echo "!!! backup FAIL $TIMESTAMP $INTERVAL" >> $LOG
     exit 1 # terminate and indicate error
 fi

 # clean up backup directory
 BACKUP_FILES=$BACKUP_DIR/*.sql
 case $INTERVAL in
   "hourly")
     KEEP=24
     ;;
   "daily")
     KEEP=7
     ;;
   "weekly")
     KEEP=4
     ;;
   "monthly")
     KEEP=12
     ;;
   "manual")
     KEEP=999 # don't automatically delete manual backups
     ;;
 esac

 # evaluate which files to delete from directory
 for BACKUP in $BACKUP_FILES; do
   # if (BACKUP_FILES quantity > KEEP)
   # and if (BACKUP age in minutes) > (minutes ago)
     # delete backup
   ARR=($BACKUP_FILES) # convert to array
   LEN=${#ARR[@]} # length of array

   # if we have too many backups...
   if (($LEN > $KEEP)); then
     # ...delete the backup.
     rm $BACKUP
   fi
 done
}

# run particular backup scripts depending on options
while getopts "hdwma" arg; do
 case $arg in
   h)
     backup "hourly"
     ;;
   d)
     backup "daily"
     ;;
   w)
     backup "weekly"
     ;;
   m)
     backup "monthly"
     ;;
   a)
     # a stands for all; backup everywhere
     backup "hourly"
     backup "daily"
     backup "monthly"
     ;;
   *)
     echo "Error: command not recognized"
     echo "!!! backup FAIL $TIMESTAMP illegal option in '$1'" >> $LOG
     ;;
 esac
done

這是我的日誌文件的範例,只是顯示了問題:

...
√   backup OK   2017-02-17.22-00-01 hourly
√   backup OK   2017-02-17.23-00-01 hourly
√   backup OK   2017-02-18.00-00-02 hourly
√   backup OK   2017-02-18.00-05-01 daily
!!! backup FAIL 2017-02-18.00-10-02 weekly
√   backup OK   2017-02-18.01-00-01 hourly
√   backup OK   2017-02-18.02-00-02 hourly
√   backup OK   2017-02-18.03-00-02 hourly
√   backup OK   2017-02-18.04-00-02 hourly
√   backup OK   2017-02-18.05-00-01 hourly
√   backup OK   2017-02-18.06-00-01 hourly
√   backup OK   2017-02-18.07-00-01 hourly
√   backup OK   2017-02-18.08-00-02 hourly
√   backup OK   2017-02-18.09-00-02 hourly
√   backup OK   2017-02-18.10-00-01 hourly
√   backup OK   2017-02-18.11-00-04 hourly
√   backup OK   2017-02-18.12-00-03 hourly
√   backup OK   2017-02-18.13-00-02 hourly
√   backup OK   2017-02-18.14-00-02 hourly
√   backup OK   2017-02-18.15-00-01 hourly
√   backup OK   2017-02-18.16-00-02 hourly
√   backup OK   2017-02-18.17-00-04 hourly
√   backup OK   2017-02-18.18-00-02 hourly
√   backup OK   2017-02-18.19-00-02 hourly
√   backup OK   2017-02-18.20-00-02 hourly
√   backup OK   2017-02-18.21-00-02 hourly
√   backup OK   2017-02-18.22-00-03 hourly
√   backup OK   2017-02-18.23-00-02 hourly
√   backup OK   2017-02-19.00-00-03 hourly
√   backup OK   2017-02-19.00-05-02 daily
√   backup OK   2017-02-19.01-00-03 hourly
√   backup OK   2017-02-19.02-00-02 hourly
√   backup OK   2017-02-19.03-00-01 hourly
...

這個命令:

sudo crontab -u my_user_group_name -e

結合備份目錄的各種使用者和組所有權:

drwxr-xr-x. 2 libsys  libsys   4096 Feb 20 00:05 daily
drwxrwxr-x. 2 root    backup   4096 Feb 20 10:00 hourly
-rw-rw-r--. 1 root    backup  35644 Feb 20 10:00 log.txt
drwxrwxr-x. 2 root    backup   4096 Feb 13 11:23 manual
drwxrwxr-x. 2 aberry3 aberry3  4096 Feb  6 10:36 monthly
drwxrwxr-x. 2 aberry3 aberry3  4096 Feb  6 10:36 weekly

看起來很腥 我猜實際的使用者——假設你並沒有一個真正的使用者my_user_group_name——不是aberry3。如果我要大膽猜測,我會說libsys正在執行的腳本是組的成員backup但不是aberry3組的成員。

由於無論如何您都是在腳本中創建目錄,因此請嘗試重命名現有目錄並讓腳本使用執行腳本的實際使用者的所有者/組來創建它們。

引用自:https://serverfault.com/questions/832328