为什么备份脚本使用 cron 会失败?

为什么备份脚本使用 cron 会失败?

因此,我正在对数据库进行自动备份。备份脚本在手动运行以及 Cron 运行预定的每小时和每日备份时均能正常工作。但是,每周和每月备份都会失败。

我(显然)不确定,但我认为我的问题出在 cron 配置上。也许是因为脚本在午夜多次运行而导致冲突?我不确定这是否可能,但如果可能的话,我希望得到有关微调 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 ([email protected]) (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 运行期间发生,但其他 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
...

答案1

此命令:

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

由于您无论如何都要在脚本中创建目录,请尝试重命名现有目录并让脚本使用运行脚本的实际用户的所有者/组来创建它们。

答案2

尝试,

sudo chown root:每周备份

答案3

向脚本添加更多日志记录。

在脚本的第一行添加“-x”。

#!/bin/bash -x

这将为您提供发送到“MAILTO”cron 选项中指定的地址的电子邮件中更详细的脚本输出。

此外,根据文档(https://wp-cli.org/commands/db/export/)你可以在“wp db export”命令中添加“--debug”。试试这个。

/usr/local/bin/wp db export --debug $FILENAME

您可以发布脚本失败时收到的邮件内容,这应该为您/我们提供足够的数据来查明问题。

相关内容