This script will start a scrub on each ZFS pool (one at a time) and will send an e-mail or display the result when everyting is completed. I wrote this script to launch each scrub one after the other and a summary by e-mail that can tell me how much time it took to each ZFS scrub.
Put this script on your FreeNAS box using the File Manager or directly at the shell by copy-pasting it. I put it in “/mnt/usb-data/bin/scrub.sh”.
To make it run automatically, go into System –> Advanced –> Cron and add it as Monthly cron job.
NOTE: Don’t forget to change the e-mail addresses in the script!
[email protected] [email protected]
Here’s the script:
#!/bin/bash #VERSION: 0.2 #AUTHOR: gimpe #EMAIL: gimpe [at] hype-o-thetic.com #WEBSITE: https://blog.gimpe.com #DESCRIPTION: Created on FreeNAS 0.7RC1 (Sardaukar) # This script will start a scrub on each ZFS pool (one at a time) and # will send an e-mail or display the result when everyting is completed. #CHANGELOG # 0.2: 2009-08-27 Code clean up # 0.1: 2009-08-25 Make it work #SOURCES: # http://aspiringsysadmin.com/blog/2007/06/07/scrub-your-zfs-file-systems-regularly/ # http://www.sun.com/bigadmin/scripts/sunScripts/zfs_completion.bash.txt # http://www.packetwatch.net/documents/guides/2009073001.php # e-mail variables [email protected] [email protected] SUBJECT="$0 results" BODY="" # arguments VERBOSE=0 SENDEMAIL=1 args=("$@") for arg in $args; do case $arg in "-v" | "--verbose") VERBOSE=1 ;; "-n" | "--noemail") SENDEMAIL=0 ;; "-a" | "--author") echo "by gimpe at hype-o-thetic.com" exit ;; "-h" | "--help" | *) echo " usage: $0 [-v --verbose|-n --noemail] -v --verbose output display -n --noemail don't send an e-mail with result -a --author display author info (by gimpe at hype-o-thetic.com) -h --help display this help " exit ;; esac done # work variables ERROR=0 SEP=" - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - " RUNNING=1 # commands & configuration ZPOOL=/sbin/zpool PRINTF=/usr/bin/printf MSMTP=/usr/local/bin/msmtp MSMTPCONF=/var/etc/msmtp.conf # print a message function _log { DATE="`date +"%Y-%m-%d %H:%M:%S"`" # add message to e-mail body BODY="${BODY}$DATE: $1n" # output to console if verbose mode if [ $VERBOSE = 1 ]; then echo "$DATE: $1" fi } # find all pools pools=$($ZPOOL list -H -o name) # for each pool for pool in $pools; do # start scrub for $pool _log "starting scrub on $pool" zpool scrub $pool RUNNING=1 # wait until scrub for $pool has finished running while [ $RUNNING = 1 ]; do # still running? if $ZPOOL status -v $pool | grep -q "scrub in progress"; then sleep 60 # not running else # finished with this pool, exit _log "scrub ended on $pool" _log "`$ZPOOL status -v $pool`" _log "$SEP" RUNNING=0 # check for errors if ! $ZPOOL status -v $pool | grep -q "No known data errors"; then _log "data errors detected on $pool" ERROR=1 fi fi done done # change e-mail subject if there was error if [ $ERROR = 1 ]; then SUBJECT="${SUBJECT}: ERROR(S) DETECTED" fi # send e-mail if [ $SENDEMAIL = 1 ]; then $PRINTF "From:$FROMnTo:$TOnSubject:$SUBJECTnn$BODY" | $MSMTP --file=$MSMTPCONF -t fi
Here’s what the e-mail content looks like:
2009-09-01 02:00:01: starting scrub on backup 2009-09-01 02:35:19: scrub ended on backup 2009-09-01 02:35:19: pool: backup state: ONLINE scrub: scrub completed with 0 errors on Tue Sep 1 02:34:50 2009 config: NAME STATE READ WRITE CKSUM backup ONLINE 0 0 0 mirror ONLINE 0 0 0 ad8 ONLINE 0 0 0 ad10 ONLINE 0 0 0 errors: No known data errors 2009-09-01 02:35:19: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2009-09-01 02:35:19: starting scrub on data 2009-09-01 02:41:24: scrub ended on data 2009-09-01 02:41:24: pool: data state: ONLINE scrub: scrub completed with 0 errors on Tue Sep 1 02:40:50 2009 config: NAME STATE READ WRITE CKSUM data ONLINE 0 0 0 ad6 ONLINE 0 0 0 errors: No known data errors 2009-09-01 02:41:24: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2009-09-01 02:41:24: starting scrub on media 2009-09-01 05:41:58: scrub ended on media 2009-09-01 05:41:58: pool: media state: ONLINE scrub: scrub completed with 0 errors on Tue Sep 1 05:41:00 2009 config: NAME STATE READ WRITE CKSUM media ONLINE 0 0 0 ad14 ONLINE 0 0 0 errors: No known data errors 2009-09-01 05:41:58: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Please, leave me a comment if you use it to let me know what you think!
Many thanks for this script. I’ve written a blogpost about scrubbing and take snapshots and I’ve added a link to your website…
See here -> http://harryd71.blogspot.com/2009/10/freenas-07-zfs-snapshots-and-scrubbing.html
Web seems to kill the formatting, so I need to make the following changes to get this to work:
*there is a missing ` mark at the end of the last line of each of the hourly/daily files.
*had to replace $1 with $pool throughout
*firefox doesn’t change & quot marks back to double quotes, so had to find and replace. FormatSelector gets tripped up by the same issues.
I am sorry for the incovienient, I updated it and tested the “copy to clipboard” button in the upper right corner of the code box and the result is now right.
Strange the “$1” in the log function looks fine to me…
Running the script with two arguments (e.g. “./scrub.sh -n -v”) causes the second argument to be ignored under FreeNAS 0.7.2. I changed “args=(“$@”)” to read “args=(“$*”)” and all is well. The other choice is to put both the arguments to scrub.sh in double quotes but I don’t believe this would be intuitive to most people.