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 {})' \;

したがって、検索は正しく機能し、それ自体で次のようなものが出力されます。

/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

0

ここでたくさん壊れました。

  • すべての caps 変数は慣例により環境変数であり、スクリプトでは使用しないでください。
  • 代わりに従来のバッククォートを使用する$()
  • 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 つの最新のものをスキップします。残りの名前に一致する完全なディレクトリ ファイルと増分ディレクトリ ファイルから削除します。

これは、もちろんタイミング攻撃を除いて、本質的に安全なバージョンです。

誤って削除しないように定義rmしました。それが正しいことを確認したら、実際の削除のためechoに元に戻します。rm

于 2013-08-13T02:00:47.000 に答える