Saturday, August 13, 2011

使用 crontab 管理 ZFS snapshot

近期終於將之前延遲已久的 ZFS storage 計畫實現. 已試過當 raidz 硬碟發生問題時, 使用 zfs replace 更換硬碟. 當然就會想用 snapshot 這個重要的功能. 所以就動手寫了簡單的 shell script 搭配 crontab 做自動化管理.

1. 簡單指令
觀察 zpool 清單, 狀態
   # zpool list
   # zpool status

   觀察 ZFS volume 清單
   # zfs list

   觀察 snapshot 清單 (/usr/ports/sysutils/freebsd-snapshot)
   # snapshot list

2. shell script
#!/usr/local/bin/bash

PATH=$PATH

LOGFILE="/var/log/snapshotfs.log"
TODAY=`date +"%Y%m%d"`
CHKPARA=0

if [ -n "$1" ]; then
 fstype="$1"
 shift
else
 CHKPARA=1
fi


if [ -n "$1" ]; then
 sstype="$1"
 shift
else
 CHKPARA=1
fi


if [ -n "$1" ]; then
 maxnum="$1"
 shift
else
 CHKPARA=1
fi


if [ -n "$1" ]; then
 volpath="$1"
 shift
else
 CHKPARA=1
fi

if [ $CHKPARA -eq 1 ]; then
 echo "Usage: $0 fstype sstype maxnum /filesystem|volume_path"
 echo "Example: $0 zfs [H|D|W|M|Q|Y] 7 /databackup/backup"
 exit 1
else
 touch $LOGFILE
 echo `date +"%Y/%m/%d %H:%M:%S"` >> $LOGFILE
 echo "$0 $fstype $sstype $maxnum $volpath" >> $LOGFILE
 echo "Check parameters for taking a snapshot of $volpath($fstype)." >> $LOGFILE
fi

if [ -d $volpath ]; then
 if [ $fstype = 'zfs' ]; then
  if [ -d $volpath/.zfs/snapshot ]; then
   echo "Check path : OK" >> $LOGFILE
  else
   echo "Check path : Failed, snapshot folder does not exist." >> $LOGFILE
   exit 1
  fi
 elif [ $fstype = 'ufs' ]; then
  if [ -d $volpath/.snap ]; then
   echo "Check path : OK" >> $LOGFILE
  else
   echo "Check path : Failed, snapshot folder does not exist." >> $LOGFILE
   exit 1
  fi
 else
  echo "Unsupported file system $fstype" >> $LOGFILE
  exit 1
 fi
else
 echo "Check path : Failed, filesystem|volume_path does not exist." >> $LOGFILE
 exit 1
fi

if [ $maxnum -gt 0 ]; then
 echo "Check maxnum : OK" >> $LOGFILE
else
 echo "Check maxnum : Failed, must input positive integer." >> $LOGFILE
        exit 1
fi

if [ $fstype = 'zfs' ]; then
 echo "ZFS" >> $LOGFILE

 case $sstype in
 H)  echo "Hourly Snapshot" >> $LOGFILE
   TODAY=`date +"%Y%m%d%H"`
   ;;
 D)  echo "Daily Snapshot" >> $LOGFILE
   ;;
 W)  echo "Weekly Snapshot" >> $LOGFILE
   ;;
 M)  echo "Monthly Snapshot" >> $LOGFILE
   ;;
 Q)  echo "Quaterly Snapshot" >> $LOGFILE
   ;;
 Y)  echo "Yearly Snapshot" >> $LOGFILE
   ;;
 *)  echo "sstype must be H | D | W | M | Q | Y " >> $LOGFILE
   exit 1
 esac

 #Snapshot
 if [ -d $volpath/.zfs/snapshot/$sstype$TODAY ]; then
  echo "Had snapshot($volpath $sstype$TODAY)." >> $LOGFILE
 else
  echo "Take a snapshot of $volpath." >> $LOGFILE
  zfs snapshot `zfs list -H -o name ${volpath}`@${sstype}${TODAY}
 fi

 #Remove more old snapshot

 KEEPSSNUM=$maxnum
 REALSSNUM=`ls $volpath/.zfs/snapshot/ | grep $sstype | wc -l`
 RMSSNUM=`expr $REALSSNUM - $KEEPSSNUM`
 RMSSID=""

 if [ $RMSSNUM -gt 0 ]; then
  for RMSSID in `ls $volpath/.zfs/snapshot/ | grep $sstype | sort -n | head -n $RMSSNUM | sed -e 's/\///'`
  do
   if [ -d $volpath/.zfs/snapshot/$RMSSID ]; then
    echo "Remove old snapshot($volpath $RMSSID)." >> $LOGFILE
    zfs destroy `zfs list -H -o name ${volpath}`@$RMSSID
   else
    echo "Old snapshot($volpath $RMSSID) does not exist." >> $LOGFILE
   fi
  done
 fi

elif [ $fstype = 'ufs' ]; then
 echo "UFS" >> $LOGFILE

 case $sstype in
 H) echo "Hourly Snapshot" >> $LOGFILE
  sskey='Hourly'
  ;;
 D) echo "Daily Snapshot" >> $LOGFILE
  sskey='Daily'
  ;;
 W) echo "Weekly Snapshot" >> $LOGFILE
  sskey='Weekly'
  ;;
 M) echo "Monthly Snapshot" >> $LOGFILE
  sskey='Monthly'
  ;;
 Q) echo "Quaterly Snapshot" >> $LOGFILE
  sskey='Quaterly'
  ;;
 Y) echo "Yearly Snapshot" >> $LOGFILE
  sskey='Yearly'
  ;;
 *) echo "sstype must be H | D | W | M | Q | Y " >> $LOGFILE
  exit 1
 esac
 
 #Snapshot
 echo "Take a snapshot UFS ${volpath}" >> $LOGFILE
 /usr/local/sbin/snapshot make -g${maxnum} ${volpath}:${sskey}
else
 echo "Unsupported file system $fstype" >> $LOGFILE
fi
3. crontab 排程自動化

### ZFS snapshot
### Hourly
45      *       *       *       *       root    /PATH/TO/zfs_snapshot_hourly.sh
### 3 Hourly
50      */3     *       *       *       root    /PATH/TO/zfs_snapshot_3hourly.sh
### Daily
0       23      *       *       *       root    /PATH/TO/zfs_snapshot_daily.sh
### Weekly
20      23      *       *       1       root    /PATH/TO/zfs_snapshot_weekly.sh
### Monthly
40      23      1       *       *       root    /PATH/TO/zfs_snapshot_monthly.sh
### Quaterly
53      23      1       1,4,7,10        *       *       root    /PATH/TO/zfs_snapshot_quaterly.sh
### Yearly
55      23      31      12      *       root    /PATH/TO/zfs_snapshot_yearly.sh


#!/usr/local/bin/bash

PATH=$PATH

### ZFS snapshot               SSTYPE SSCOUNT
### H for hourly or 3hourly ex: H 8
### D for daily             ex: D 7
### W for weekly            ex: W 4
### M for monthly           ex: M 6
### Q for quaterly          ex: Q 4
### Y for yearly            ex: Y 3

/root/root_scripts/snapshotfs.sh zfs SSTYPE SSCOUNT /zfs-volumn/path1
/root/root_scripts/snapshotfs.sh zfs SSTYPE SSCOUNT /zfs-volumn/path2
/root/root_scripts/snapshotfs.sh zfs SSTYPE SSCOUNT /zfs-volumn/path3

1 comment:

Computer Geek said...

使用 zpool add STORAGE-NAME cache DEVICE-NAME1 ... 加入 cache device(SLC SSD)可以啟動 ZFS L2ARC 功能, 有效加速 ZFS. 替換 cache device 可使用 zpool offline STORAGE-NAME DEVICE-NAME 再 zpool remove STORAGE-NAME DEVICE-NAME. 再加進新的 cache device.