Automated/unattended backup of Raspberry/Domoticz
Posted: Friday 09 June 2017 18:10
Hi All,
Maybe this is interesting for some Domoticz/Raspberry users who want to make a backup of there system.
Last weeks I changed some existing scripts and added some other functionality to make an automated backup of my Rasspberry which runs Domoticz.
There are three scripts I share :
-One to make a backup on the same SD card
-One to copy the backup to another memory card in a USB card reader on the same PI
-One to copy the backup to my HiDrive (Strato) cloud storage via rsync
Every Sunday morning a fresh backup is made, copied and uploaded in my cloud via crontab.
Credits go to SYSMATT and many others who answered several questions on stackoverflow.
I am not an expert in bash coding so I think there will be some improvements possible and I know there are other solutions to transfer the data in a more secure way but its fine for me right now.
PS: Make a user variable with the name "Backupfile" as a string, change the parameters according your setup and be sure the necessary directory's exist on your PI. Store the password of HiDrive in a file called /home/pi/HiDrive/HiDrivePass and chmod this file so only the root user can read this.
Backup script
Restore SD card
Copy to HiDrive
Have fun with it
JJ
Maybe this is interesting for some Domoticz/Raspberry users who want to make a backup of there system.
Last weeks I changed some existing scripts and added some other functionality to make an automated backup of my Rasspberry which runs Domoticz.
There are three scripts I share :
-One to make a backup on the same SD card
-One to copy the backup to another memory card in a USB card reader on the same PI
-One to copy the backup to my HiDrive (Strato) cloud storage via rsync
Every Sunday morning a fresh backup is made, copied and uploaded in my cloud via crontab.
Credits go to SYSMATT and many others who answered several questions on stackoverflow.
I am not an expert in bash coding so I think there will be some improvements possible and I know there are other solutions to transfer the data in a more secure way but its fine for me right now.
PS: Make a user variable with the name "Backupfile" as a string, change the parameters according your setup and be sure the necessary directory's exist on your PI. Store the password of HiDrive in a file called /home/pi/HiDrive/HiDrivePass and chmod this file so only the root user can read this.
Backup script
Code: Select all
#!/bin/bash
# 20140804-1708 Matthew E Hoskins / Twitter: @sysmatt (c) GNU GPL
# Edited bij John Westdorp 2017-03-18
#set -x # debugging
# print debug text on screen or in a log file
printscreen=FALSE
#Domoticz Parameters
domoticzIp=192.168.x.xx
domoticzPort=xxxx
# clear the logfile otherwise it grows and grows and.....
truncate -s 0 /var/log/backup_restore/templogFile_backup.txt
#The logFile is located /var/log/backup_restore
function printscreen_or_log {
if [ "$printscreen" == "TRUE" ]
then
echo "$(date "+%FT%T"): Backup_script: ${1}"
else
echo "$(date "+%FT%T"): Backup_script: ${1}" >> "/var/log/backup_restore/templogFile_backup.txt"
fi
}
bomb () {
printscreen_or_log "BOMB: ${1}"
exit 1
}
# Start backup
# Default destination directory
DSTDIR=/home/pi/backups
DEFAULT_DFILE="${DSTDIR}/pi.`uname -n`.`date +%Y%m%d%H%M%S`.backup.tar.gz"
# If we get a filename on the command line, use it instead of the default.
DFILE="${1:-$DEFAULT_DFILE}"
DEST_DIR_SANITY=`dirname "${DFILE}"`
# Make sure the destination exists
[ -d "${DEST_DIR_SANITY}" ] || bomb "Destination directory ${DEST_DIR_SANITY} does not exist"
# Store the filename in a user variable
curl -s $domoticzIp":"$domoticzPort"/json.htm?type=command¶m=updateuservariable&vname=Backupfile&vtype=2&vvalue="${DFILE}
# Be sure to start backup ? (unattendant backup via CRON job, comment out read command)
printscreen_or_log "******************** Backup script is started ********************"
#read -p "PRESS ENTER to start backup, Press CTRL-c to abort"
# check state of domoticz and stop the proces if running so files and the database will be closed
status=`curl -s -i -H "Accept: application/json" "http://"$domoticzIp":"$domoticzPort"/json.htm?type=devices&rid=1" | grep "status"| awk -F: '{print $2}'|sed 's/,//'| sed 's/\"//g'`
if [ $status ]
then
printscreen_or_log "Domoticz is running , it will be stopped before starting backup."
sudo service domoticz.sh stop
sleep 30
else
printscreen_or_log "Domoticz isn't running, start backup immediately"
fi
# Run the tar archive
printscreen_or_log "Start making backup, this will take a while......"
tar --exclude="${DFILE}" --one-file-system -cvzf "${DFILE}" / /boot
printscreen_or_log "Created archive: ${DFILE}"
# Start Domoticz again, first check the status
status=`curl -s -i -H "Accept: application/json" "http://"$domoticzIp":"$domoticzPort"/json.htm?type=devices&rid=1" | grep "status"| awk -F: '{print $2}'|sed 's/,//'| sed 's/\"//g'`
if [ $status ]
then
printscreen_or_log "Backup is finished, Domoticz has already been started"
else
printscreen_or_log "Backup is finished, Domoticz was offline, attempting a restart."
sudo service domoticz.sh stop
sleep 30
sudo service domoticz.sh start
fi
printscreen_or_log "******************** Backup script is finished ********************"
# END
Code: Select all
#!/bin/bash
# 20140804-1708 Matthew E Hoskins / Twitter: @sysmatt (c) GNU GPL
# Edited bij John Westdorp 2017-05-21
# print debug text on screen or in a log file
printscreen=FALSE
#Domoticz Parameters
domoticzIp=192.168.x.xx
domoticzPort=xxxx
backup_file_name_IDX=xx
# clear the logfile otherwise it grows and grows and.....
truncate -s 0 /var/log/backup_restore/templogFile_restore.txt
#The logFile is located /var/log/backup_restore
function printscreen_or_log {
if [ "$printscreen" == "TRUE" ]
then
echo "$(date "+%FT%T"): Backup_script: ${1}"
else
echo "$(date "+%FT%T"): Backup_script: ${1}" >> "/var/log/backup_restore/templogFile_restore.txt"
fi
}
printscreen_or_log "******************** Restore script is started ********************"
# get the SD CARD DEVICE name of the USB memory card to restore the backup image on it or supply the device name as argument ie /dev/sda
export USBKEYS=($( # Declaration of *array* 'USBKEYS'
grep -Hv ^0$ /sys/block/*/removable | # search for *not 0* in `removable` flag of all devices
sed s/removable:.*$/device\\/uevent/ | # replace `removable` by `device/uevent` on each line of previous answer
xargs grep -H ^DRIVER=sd | # search for devices drived by `SD`
sed s/device.uevent.*$/size/ | # replace `device/uevent` by 'size'
xargs grep -Hv ^0$ | # search for devices having NOT 0 size
cut -d / -f 4 # return only 4th part `/` separated
))
#for dev in ${USBKEYS[@]} ;do # for each devices in USBKEY...
# printscreen_or_log $dev \"$(r # echo device name and content of model file
# sed -e s/\ *$//g </sys/block/$dev/device/model
# )\" ;
# done
# I have only one USB memory card in my Raspberry so there is only one device name in the array
DEFAULT_SDCARD_DEVICE=/dev/${USBKEYS[0]}
# get the backup_file_name from the uservariable or supply the file name as argument
DEFAULT_PI_BACKUP_SLASH=$(curl -s "http://$domoticzIp:$domoticzPort/json.htm?type=command¶m=getuservariable&idx=$backup_file_name_IDX" | grep "Value")
DEFAULT_PI_BACKUP_SLASH="${DEFAULT_PI_BACKUP_SLASH##*Value\" : \"}"
DEFAULT_PI_BACKUP_SLASH=${DEFAULT_PI_BACKUP_SLASH//\",/}
# If we get a device name and/or a filename on the command line, use it instead of the defaults.
SDCARD_DEVICE="${1:-$DEFAULT_SDCARD_DEVICE}"
PI_BACKUP_SLASH="${2:-$DEFAULT_PI_BACKUP_SLASH}"
shift; shift;
# Any remaining args are added to TAR command line
printscreen_or_log "SD card device ==>${SDCARD_DEVICE}<=="
printscreen_or_log "Backup_file_name ==>${PI_BACKUP_SLASH}<=="
# Extra operations which can be done in ENV Vars
# PI_OVERWRITE_ETC_HOSTNAME="new-hostname"
# PI_OPENVPN_CONFIG_FILE="/some/source/client.conf"
# Temp random mountpoint under /tmp
MOUNTPOINT="/tmp/pi.sd.${RANDOM}${$}"
bomb (){
printscreen_or_log "BOMB: ${1}"
exit 1
}
[ -x "/sbin/mkfs.vfat" ] || bomb "/sbin/mkfs.vfat Missing"
printscreen_or_log ""
printscreen_or_log "=== ${SDCARD_DEVICE} Current Partition Table - To be destroyed! ==="
parted --script ${SDCARD_DEVICE} "print"
printscreen_or_log ""
# Be sure to write image ? (unattendant writing via CRON job, comment out read command)
#read -p "PRESS ENTER to DESTROY ${SDCARD_DEVICE}, Press CTRL-c to abort"
parted --script "${SDCARD_DEVICE}" "mklabel msdos"
parted --script "${SDCARD_DEVICE}" "mkpart primary fat16 1MiB 64MB"
parted --script "${SDCARD_DEVICE}" "mkpart primary ext4 64MB -1s"
parted --script "${SDCARD_DEVICE}" print
mkfs.vfat "${SDCARD_DEVICE}1"
mkfs.ext4 -F -j "${SDCARD_DEVICE}2"
mkdir -p "${MOUNTPOINT}"
mount "${SDCARD_DEVICE}2" "${MOUNTPOINT}"
mkdir -p "${MOUNTPOINT}/boot"
mount "${SDCARD_DEVICE}1" "${MOUNTPOINT}/boot"
df -h "${MOUNTPOINT}"
df -h "${MOUNTPOINT}/boot"
# unattendant writing via CRON job, comment out read command
#read -p "Press ENTER To begin image restore"
printscreen_or_log "Image restore started at device: ${SDCARD_DEVICE}, this will take a while......"
tar $@ -xvzf "${PI_BACKUP_SLASH}" -C "${MOUNTPOINT}"
# Begin NOOBS fixup / Recommended by @KevinSidwar / 20140829-1744-MEH
ORIG_SLASHDEV_FOUND=`cat "${MOUNTPOINT}/etc/fstab"| grep " / " |grep -v "^#" |awk '{ print $1; }'`
ORIG_BOOTDEV_FOUND=`cat "${MOUNTPOINT}/etc/fstab"| grep " /boot " |grep -v "^#" |awk '{ print $1; }'`
# Hardcoded
NEW_SLASHDEV="/dev/mmcblk0p2"
NEW_BOOTDEV="/dev/mmcblk0p1"
# Defaults just in case the above search of fstab is a miss
ORIG_SLASHDEV="${ORIG_SLASHDEV_FOUND:-$NEW_SLASHDEV}"
ORIG_BOOTDEV="${ORIG_BOOTDEV_FOUND:-$NEW_BOOTDEV}"
printscreen_or_log "ORIG_SLASHDEV[${ORIG_SLASHDEV}] NEW_SLASHDEV[${NEW_SLASHDEV}] ORIG_BOOTDEV[${ORIG_BOOTDEV}] NEW_BOOTDEV[${NEW_BOOTDEV}]"
FILE_FSTAB="${MOUNTPOINT}/etc/fstab"
FILE_CMDLINE="${MOUNTPOINT}/boot/cmdline.txt"
FILE_OS_CONFIG_JSON="${MOUNTPOINT}/boot/os_config.json"
if [ "${ORIG_SLASHDEV}" != "${NEW_SLASHDEV}" -o "${ORIG_BOOTDEV}" != "${NEW_BOOTDEV}" ]
then
printscreen_or_log "CONFIGURATION CONVERSION NECESSARY - Devices do not match, modifying files. "
THISFILE="${FILE_FSTAB}"
if [ -e "${THISFILE}" ]
then
printscreen_or_log "Fixing ${THISFILE}"
cp -f "${THISFILE}" "${THISFILE}.old"
cat "${THISFILE}.old" |sed -e "s#${ORIG_SLASHDEV}#%NEW_SLASHDEV%# ; s#${ORIG_BOOTDEV}#%NEW_BOOTDEV%#" > "${THISFILE}.i"
cat "${THISFILE}.i" |sed -e "s#%NEW_SLASHDEV%#${NEW_SLASHDEV}# ; s#%NEW_BOOTDEV%#${NEW_BOOTDEV}#" >"${THISFILE}"
rm -f "${THISFILE}.i"
fi
THISFILE="${FILE_CMDLINE}"
if [ -e "${THISFILE}" ]
then
printscreen_or_log "Fixing ${THISFILE}"
cp -f "${THISFILE}" "${THISFILE}.old"
cat "${THISFILE}.old" |sed -e "s#${ORIG_SLASHDEV}#%NEW_SLASHDEV%# ; s#${ORIG_BOOTDEV}#%NEW_BOOTDEV%#" > "${THISFILE}.i"
cat "${THISFILE}.i" |sed -e "s#%NEW_SLASHDEV%#${NEW_SLASHDEV}# ; s#%NEW_BOOTDEV%#${NEW_BOOTDEV}#" >"${THISFILE}"
rm -f "${THISFILE}.i"
fi
THISFILE="${FILE_OS_CONFIG_JSON}"
if [ -e "${THISFILE}" ]
then
printscreen_or_log "Fixing ${THISFILE}"
cp -f "${THISFILE}" "${THISFILE}.old"
cat "${THISFILE}.old" |sed -e "s#${ORIG_SLASHDEV}#%NEW_SLASHDEV%# ; s#${ORIG_BOOTDEV}#%NEW_BOOTDEV%#" > "${THISFILE}.i"
cat "${THISFILE}.i" |sed -e "s#%NEW_SLASHDEV%#${NEW_SLASHDEV}# ; s#%NEW_BOOTDEV%#${NEW_BOOTDEV}#" >"${THISFILE}"
rm -f "${THISFILE}.i"
fi
fi
# End Noobs fixup
if [ -n "${PI_OVERWRITE_ETC_HOSTNAME}" ]
then
# Write a new /etc/hostname
printscreen_or_log "Writing new /etc/hostname with [${PI_OVERWRITE_ETC_HOSTNAME}] to ${MOUNTPOINT}/etc/hostname"
printscreen_or_log "${PI_OVERWRITE_ETC_HOSTNAME}" > "${MOUNTPOINT}/etc/hostname"
fi
if [ -e "${PI_OPENVPN_CONFIG_FILE}" ]
then
printscreen_or_log "Writing OpenVPN config [${PI_OPENVPN_CONFIG_FILE}] to ${MOUNTPOINT}/etc/openvpn/"
rm -f ${MOUNTPOINT}/etc/openvpn/*.conf
cp -f "${PI_OPENVPN_CONFIG_FILE}" "${MOUNTPOINT}/etc/openvpn/"
fi
printscreen_or_log =DONE=
printscreen_or_log "The SD is mounted at: ${MOUNTPOINT}"
printscreen_or_log "Now would be a good time to make modifications in another shell session..."
# unattendant writing via CRON job, comment out read command
#read -p "Press ENTER To unmount or CTRL-c to exit leaving mounted."
printscreen_or_log "Unmounting. This may take a moment..."
set -x
umount "${MOUNTPOINT}/boot"
umount "${MOUNTPOINT}"
printscreen_or_log "******************** Restore script is finished ********************"
# END
Code: Select all
#!/bin/bash
# 20170604-001 John Westdorp (c) GNU GPL
# print debug text on screen or in a log file
printscreen=FALSE
#Domoticz Parameters
domoticzIp=192.168.x.xx
domoticzPort=xxxx
backup_file_name_IDX=xx
#Variables
HIDRIVE_HOSTNAME="rsync.hidrive.strato.com"
HIDRIVE_USERNAME="xxxxxxxx"
HIDRIVE_PASSWORD=$(cat /home/pi/HiDrive/HiDrivePass)
# Source and destination directory
SRCDIR="/home/pi/backups"
DESTDIR="/users/xxxxxxx/Raspberry_backups"
# clear the logfile otherwise it grows and grows and.....
truncate -s 0 /var/log/backup_restore/templogFile_copy_HiDrive.txt
#The logFile is located /var/log/backup_restore
function printscreen_or_log {
if [ "$printscreen" == "TRUE" ]
then
echo "$(date "+%FT%T"): Backup_script: ${1}"
else
echo "$(date "+%FT%T"): Backup_script: ${1}" >> "/var/log/backup_restore/templogFile_copy_HiDrive.txt"
fi
}
# Start copying
printscreen_or_log "******************** Copy backups to HiDrive script is started ********************"
# Be sure to start copying (unattendant copying via CRON job, comment out read command)
#read -p "PRESS ENTER to start backup, Press CTRL-c to abort"
# get the latest backup_file_name from the uservariable
PI_BACKUP=$(curl -s "http://$domoticzIp:$domoticzPort/json.htm?type=command¶m=getuservariable&idx=$backup_file_name_IDX" | grep "Value")
PI_BACKUP=${PI_BACKUP##*Value\" : \"}
PI_BACKUP=${PI_BACKUP//\",/}
printscreen_or_log "Backup_file ==>${PI_BACKUP}<== will be copied to HiDrive"
if [ -f $PI_BACKUP ]
then
# Run the copy
printscreen_or_log "Start copying, this will take a while......"
sshpass -p $HIDRIVE_PASSWORD rsync -rltDvze "ssh" $SRCDIR $HIDRIVE_USERNAME@$HIDRIVE_HOSTNAME:$DESTDIR
printscreen_or_log "Backup_file ==>${PI_BACKUP}<== is succesfully copied to HiDrive"
# remove the file after copying otherwise the next backup will also contain the backup file etc. etc
rm $PI_BACKUP
printscreen_or_log "Backup_file ==>${PI_BACKUP}<== is deleted from ==>$SRCDIR<=="
else
printscreen_or_log "Error: Can't copy backup_file ==>${PI_BACKUP}<== , file not found"
fi
printscreen_or_log "******************** Backup script is finished ********************"
# END
JJ