CentOS 7サーバーで自動バックアップを実行するスクリプトを作成しました。バックアップは/ home/backupディレクトリに保存されます。スクリプトは機能しますが、バックアップが発生した後にファイルをカウントする方法を組み込み、数が5を超える場合は、最も古いバックアップを削除します。
以下は、バックアップスクリプト用のものです。
#!/bin/bash
#mysqldump variables
FILE=/home/backup/databasebk_!`date +"Y-%m-%d_%H:%M"`.sql
DATABASE=database
USER=root
PASS=my password
#backup command process
mysqldump --opt --user=${USER} --password=${PASS} ${DATABASE} > ${FILE}
#zipping the backup file
gzip $FILE
#send message to the user with the results
echo "${FILE}.gz was created:"
ls -l ${FILE}.gz
# This is where I would like to count the number of files
# in the directory and if there are more than 5 I would like
# to delete the oldest file. Any help is greatly appreciated
ありがとう-マイク
set -- /home/backup/databasebk_*
を見て、$#
が5より大きい場合、ファイルを削除します。
したがって、コードは次のようになります
set -- /home/backup/databasebk_*
while [ $# -gt 5 ]
do
echo "Removing old backup $1"
rm "$1"
shift
done
これは、選択したファイル名が自動的に「最も古いものから」の順序になるため機能します。
一貫性を保つために変数を設定します(通常はBASE
と呼びますが、好きなように呼び出すことができます)
そう
BASE=/home/backup/databasebk_
FILE=${BASE}!`date +"%Y-%m-%d_%H:%M"`.sql
....
set -- ${BASE}*
while [ $# -gt 5 ]
do
echo "Removing old backup $1"
rm "$1"
shift
done
ループのない純粋なBashでは:
ls -t | tail -n +6 | xargs -d '\n' rm
説明:
ls -t
は、現在のディレクトリにあるすべてのファイルを、変更時刻でソートされた新しいものから最初に出力します。tail -n +6
は最初の5行を無視し、6行目以降を出力します。xargs -d '\n' rm
は、渡されたファイルを1行に1つずつ削除します。ファイル名にスペースや引用符がないことが確実である場合は、xargs rm
だけを使用できます。これは、dirに5つのファイルのみを残すために必要な数のファイルを削除することに注意してください。最も古いファイルを1つだけ削除する場合は、+6
を1
に置き換えます。
このアプリケーションはスクリプトで達成しようとしているアクションをすでに実行しているため、より良いアプローチはlogrotateを使用することだと思います。テストサーバーで次のスクリプトをテストしました。
$ mysqldump -uroot -pmy5trongpass database > mydatabase.sql
$ ls
$ mydatabase.sql
最初のデータベースが作成されなかった場合のエラーの例。
#**logrotate -f** will force our new rule to run now and backup the database
#this is for testing purposes.
$ logrotate -f /etc/logrotate.d/mysql_backup
error: stat of /home/backups/mydatabase.sql failed: No such file or directory
$ cat /etc/logrotate.d/mysql_backup
/home/backups/mydatabase.sql{
create 640 root mysql
daily
rotate 2
nocompress
postrotate
mysqldump -uroot -pmy5trongpass test > mydatabase.sql;
echo "done"
endscript
}
$ logrotate -f /etc/logrotate.d/mysql_backup
$ logrotate -f /etc/logrotate.d/mysql_backup
done
$ ll
total 16
-rw-r-----. 1 root mysql 1261 Feb 3 21:46 mydatabase.sql
-rw-r-----. 1 root mysql 1261 Feb 3 21:44 mydatabase.sql.1
-rw-r-----. 1 root mysql 1261 Feb 3 21:44 mydatabase.sql.2
新しいファイルが作成され、その後に番号が表示されます。これは、次のオプションを使用して日付を表示するように変更できます
https://linux.die.net/man/8/logrotate
dateext
Archive old versions of log files adding a daily extension like YYYYMMDD instead of simply adding a number. The extension may be configured using the dateformat option.
dateformat format_string
Specify the extension for dateext using the notation similar to strftime(3) function. Only %Y %m %d and %s specifiers are allowed. The default value is -%Y%m%d. Note that also the character separating log name from the extension is part of the dateformat string. The system clock must be set past Sep 9th 2001 for %s to work correctly. Note that the datestamps generated by this format must be lexically sortable (i.e., first the year, then the month then the day. e.g., 2001/12/01 is ok, but 01/12/2001 is not, since 01/11/2002 would sort lower while it is later). This is because when using the rotate option, logrotate sorts all rotated filenames to find out which logfiles are older and should be removed.
zsh
シェルの使用:
_rm -f /home/backup/databasebk_*.sql.gz(.om[6,-1])
_
これにより、_/home/backup/databasebk_*.sql.gz
_に一致する通常のファイルのパス名のリストが作成され、ファイルの変更タイムスタンプでリストがソートされ(最近変更されたものが最初に)、要素6から最後まで抽出されます。これらのファイルは、削除のために_rm -f
_に渡されます。
glob修飾子、_(.om[6,-1])
_、通常のファイルを指定するファイル名展開パターンの最後にあります(_.
_)、変更時刻による順序付け(om
)、およびそれ6番目から最後の一致までが返されます(_[6,-1]
_)。
files=( /home/backup/* )
# files is now an array containing file names in the directory
oldest=""
if (( ${#files[@]} > 5 )) ## are there more than five?
then
for name in "${files[@]}" ## loop to find oldest
do
a=$( stat --printf=%Y "$name" )
if [ -z "$oldest" ] || (( a < age ))
then
age="$a"
oldest="$name"
fi
done
rm "$oldest"
fi
私は言う /home/backup/*
これは、そのディレクトリ内のすべてのファイルを検索します/home/backup/databasebk_*.sql.gz
代わりに、圧縮されたダンプを見つけるだけ
日付がYMDhm形式の順序になっているため、ファイルシステムに従って最も古いファイルを見つけるために「stat」を使用しています。代わりにファイル名を比較できます。
if [ -z "$oldest" ] || [ "$name" -lt "$oldest" ]
/ home/backup /にサブディレクトリがあると、このスクリプトが壊れます
始める前に、私は他の答えを最も高く評価しており、それらはプロセスの十分な理解を反映していると言いたいと思います。
私は今、あなたの立場に立って、簡単なものを探して始め、それを土台にしていきます。最初に問題を説明しましょう。
これが私のアプローチです:
ls -1 |wc -l
を使用して、ファイルの数をカウントします。これがコードです:
if [[ $(ls -1|wc -l) -gt 5 ]]; then
ls -1t |tail -n1 |xargs -n1 rm -f
fi
1行目の説明:そのディレクトリ内のファイル数が5を超えているかどうかを確認します。
2行目の説明:ファイル数が5を超えた場合にのみ実行されます(4つのファイルがあり、そのうちの1つが100日前の日付の場合、実行されません)。それらは日付でソートされ、tail
コマンドを実行して最も古いもの(リストの最後のもの)を取得します。次に、そのファイル名をxargs
コマンドに渡し、rm -f
(強制)を使用してファイルを削除します。
解決策を提供してくれた他のすべての人に感謝します!これが機能しない場合があることは知っています(6つを超えるファイル、同じ日付の2つのファイルなど)。しかし、Mikeは新しいので、シンプルに保つように努めました:)
作成rm-except-last.sh
:
#!/bin/bash -
set -o nounset
if ! (($#)); then
echo Usage: "$BASH_SOURCE" N_NOT_TO_DELETE FILES_TO_DELETE...
exit 1
fi
declare N="${1:?Missing N_NOT_TO_DELETE.}"
if ! [[ "$N" =~ ^[0-9]+$ ]]; then
echo 1>&2 -E Not a number: "$N"
exit 1
fi
shift
declare -a roll=()
while ((${#roll[@]} < N)); do
roll+=('')
done
if ! ((N)); then
rm -rfv -- "$@"
exit $?
fi
declare n=0 file=''
for file in "$@"; do
declare rmfile="${roll[n]}"
[ -n "$rmfile" ] && rm -rfv -- "$rmfile"
roll[n]="$file"
((n = (n + 1) % N))
done
次に:
$ rm-except-last.sh 5 /home/backup/databasebk_*.sql