3 # Copyright 2011 by Jan Vales <jan@jvales.net> (Someone <someone@somenet.org>)
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation, version 3 of the License.
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
14 # You should have received a copy of the GNU General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
19 # Purge old BTRFS snapshots
20 # 30 * * * * /root/somescripts/btrfs/cleanup.sh &> /dev/null
22 # This script will keep current/last day/month snapshots.
23 # This script will update current/last_day/week/month snapshots and will delete snapshots if needed (too many or low on space)
25 #set volumes to do curr/last day/month for.
26 LASTLIST="root home homeroot"
28 # Autosnaps to keep. Counting/Considering *.snap only. There should be adate_*.snap snapshots only.
33 echo "***START: `date`***"
34 if [ -e /tmp/btrfs_cleaner.lock ]; then
35 echo "Lockfile found. Assuming another instance is running. exitting."
39 touch /tmp/btrfs_cleaner.lock
40 mount /mnt/btrfs &> /dev/null
43 # Keep current and last MONTH
44 for vol in $LASTLIST; do
45 CHECK=$(grep "`date +"%Y-%m-"`" amon_curr_${vol}.txt 2> /dev/null)
46 if [ "$CHECK" == "" ]; then
47 echo "Autosnap cleaner: Rotating current month for ${vol}"
48 if [ -e "amon_curr_${vol}.snp" -a -e "amon_curr_${vol}.txt" ]; then
49 echo "Autosnap cleaner: Rotating last month for ${vol}"
50 if [ -e "amon_last_${vol}.snp" -a -e "amon_last_${vol}.txt" ]; then
51 mv "amon_last_${vol}.snp" "`cat amon_last_${vol}.txt`"
53 mv "amon_curr_${vol}.snp" "amon_last_${vol}.snp"
54 mv "amon_curr_${vol}.txt" "amon_last_${vol}.txt"
56 CANDIDATE=$(find . -maxdepth 1 -name 'aadate_'`date +"%Y-%m-"`'*_'${vol}'.snap' | sort | head -n 1)
57 if [ "$CANDIDATE" != "" ]; then
58 echo $CANDIDATE > amon_curr_${vol}.txt
59 mv $CANDIDATE amon_curr_${vol}.snp
64 # Keep current and last DAY
65 for vol in $LASTLIST; do
66 CHECK=$(grep "`date +"%Y-%m-%d"`" aday_curr_${vol}.txt 2> /dev/null)
67 if [ "$CHECK" == "" ]; then
68 echo "Autosnap cleaner: Rotating current day for ${vol}"
69 if [ -e "aday_curr_${vol}.snp" -a -e "aday_curr_${vol}.txt" ]; then
70 echo "Autosnap cleaner: Rotating last day for ${vol}"
71 if [ -e "aday_last_${vol}.snp" -a -e "aday_last_${vol}.txt" ]; then
72 mv "aday_last_${vol}.snp" "`cat aday_last_${vol}.txt`"
74 mv "aday_curr_${vol}.snp" "aday_last_${vol}.snp"
75 mv "aday_curr_${vol}.txt" "aday_last_${vol}.txt"
77 CANDIDATE=$(find . -maxdepth 1 -name 'aadate_'`date +"%Y-%m-%d"`'*_'${vol}'.snap' | sort | head -n 1)
78 if [ "$CANDIDATE" != "" ]; then
79 echo $CANDIDATE > aday_curr_${vol}.txt
80 mv $CANDIDATE aday_curr_${vol}.snp
86 # CLEAN *.snap if needed (too many or low on space)
88 while [ $LOOPDEL -eq 2 ]; do
91 btrfs fi show inthdd &> /tmp/btrfs_fishow.txt
92 SPACESIZE="`grep 'size' /tmp/btrfs_fishow.txt | sed -E 's~^.*?size ([0-9]+\.[0-9]*)GB .*?$~\1~g'`"
93 SPACEUSED="`grep 'bytes used' /tmp/btrfs_fishow.txt | sed -E 's~^.*?bytes used ([0-9]+\.[0-9]*)GB.*?$~\1~g'`"
94 SPACEALLOC="`grep 'size' /tmp/btrfs_fishow.txt | sed -E 's~^.*?GB used ([0-9]+\.[0-9]*)GB.*?$~\1~g'`"
95 rm /tmp/btrfs_fishow.txt
97 SNAPCNT="`find . -maxdepth 1 -name '*.snap' | wc -l`"
98 SPACEPERCENT="`python -c 'print int(100.0*'${SPACEUSED}'/'${SPACESIZE}')'`"
100 echo "Autosnap cleaner: Snap count min/curr/limit [${MINSNAPCNT}/${SNAPCNT}/${MAXSNAPCNT}]."
101 echo "Autosnap cleaner: Space used/alloc/size/limit [${SPACEUSED}/${SPACEALLOC}/${SPACESIZE}][${SPACEPERCENT}%/${MAXSPACEPERCENT}%]"
103 if [ $SNAPCNT -gt $MAXSNAPCNT -o $SPACEPERCENT -gt $MAXSPACEPERCENT ]; then
104 DELFILE="`find . -maxdepth 1 -name '*.snap' | sort | head -n -${MINSNAPCNT} | head -n 1`"
105 if [ $SNAPCNT -gt $MINSNAPCNT -a "$DELFILE" != "" ]; then
106 btrfs subvolume delete "${DELFILE}" && LOOPDEL=2
109 if [ "$1" == "noloop" -a $LOOPDEL -eq 2 ]; then
110 echo "Autosnap cleaner: noloop flag set. forcing break."
113 if [ $LOOPDEL -eq 2 ]; then
119 umount /mnt/btrfs &> /dev/null
120 rm /tmp/btrfs_cleaner.lock
121 ps aux | grep "\[btrfs-cleaner\]"
122 echo "***END: `date`***"