0

我无法使以下脚本(它是较大备份脚本的一部分)正常工作:

BACKUPDIR=/BACKUP/db01/physical/incremental # Backups base directory
FULLBACKUPDIR=$BACKUPDIR/full # Full backups directory
INCRBACKUPDIR=$BACKUPDIR/incr # Incremental backups directory
KEEP=5 # Number of full backups (and its incrementals) to keep
...
FIRST_DELETE=`expr $KEEP + 1` # add one to the number of backups to keep, this will be the first deleted
FILE0=`ls -ltr $FULLBACKUPDIR | awk '{print $9}' | tail -$FIRST_DELETE | head -1` # search for the first backup to be deleted
...
find $FULLBACKUPDIR -maxdepth 1 -type d ! -newer $FULLBACKUPDIR/$FILE0 -execdir echo "removing: "$FULLBACKUPDIR/$(basename {}) \; -execdir bash -c 'rm -rf $FULLBACKUPDIR/$(basename {})' \; -execdir echo "removing: "$INCRBACKUPDIR/$(basename {}) \; -execdir bash -c 'rm -rf $INCRBACKUPDIR/$(basename {})' \;

所以 find 工作正常,它自己会输出如下内容:

/BACKUPS/db01/physical/incremental/full/2013-08-12_17-51-28
/BACKUPS/db01/physical/incremental/full/2013-08-12_17-51-28
/BACKUPS/db01/physical/incremental/full/2013-08-12_17-25-07

我想要的是 -exec 来回显一行,显示正在删除的内容,然后从两个目录中删除该文件夹。

我尝试了各种方法来获取基本名称,但似乎没有任何效果。我明白了:

removing: /BACKUPS/mysql/physical/incremental/full/"/BACKUPS/mysql/physical/incremental/full/2013-08-12_17-51-28"
removing: /BACKUPS/mysql/physical/incremental/incr/"/BACKUPS/mysql/physical/incremental/full/2013-08-12_17-51-28"
removing: /BACKUPS/mysql/physical/incremental/full/"/BACKUPS/mysql/physical/incremental/full/2013-08-12_17-25-07"

当然,这些文件夹不会被删除,因为它们不存在,只是因为 -f 选项而静默失败。如果我删除 -f 我会在每个 rm 上收到“找不到”错误。

我该如何做到这一点?因为备份和部分备份可能存储在不同的存储系统中,所以我真的需要能够获取文件夹名称以在任何已知路径中使用。

4

2 回答 2

1

首先$(basename {})运行,然后替换完成。removing: "$INCRBACKUPDIR/$(basename {})removing: "$INCRBACKUPDIR/{}{}

一种解决方法可能是将其通过管道传输到 bash:

-exec echo "echo \"removing: \\\"$INCRBACKUPDIR/\$(basename {})\\\"\" | bash" \;
于 2013-08-13T01:50:06.213 回答
0

这里破了很多。

  • 所有 caps 变量都是约定的 env var,不应在脚本中使用。
  • 使用旧的反引号而不是$()
  • 解析ls(!)的输出
  • 解析ls -l(!!!)的输出
  • 扩展已知包含不带全引号的路径的变量。

为了改善这一点,您绝对需要-exec bash的是正确地,例如

-execdir bash -c 'filepath="$1" ; base=$(basename "$filepath") ; echo use $filepath and $base here' -- {} \;

但是这个怎么样:

#!/usr/bin/env bash

backup_base=/BACKUP/db01/physical/incremental
full_backup="$backup_base"/full
incremental_backup="$backup_base"/incr
keep=5
rm=echo

let n=0
while IFS= read -r -d $'\0' line ; do
    file="${line#* }"
    if [[ $n -lt $keep ]] ; then
            let n=n+1
            continue
    fi
    base=$(basename "$file")
    echo "removing: $full_backup/$base"
    "$rm" -rf -- "$full_backup"/"$base"
    echo "removing: $incremental_backup/$base"
    "$rm" -rf -- "$incremental_backup"/"$base"
done < <(find "$full_backup" -maxdepth 1 -printf '%T@.%p\0' 2>/dev/null | sort -z -r -n -t. -k1,2)

立即遍历备份目录下的文件和目录,并跳过前 5 个最新的。从与其余名称匹配的完整和增量目录文件中删除。

这是一个本质上安全的版本,当然除了定时攻击。

我已经定义rmecho避免意外删除;rm一旦您确定它是正确的,就将其换回以进行实际删除。

于 2013-08-13T02:00:47.000 回答