#!/bin/bash # # Copyright (c) 2018 Ejner Fergo efer@dtu.dk # # License: This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as published # by the Free Software Foundation; either version 3 of the License, or # (at your option) any later version. This program is distributed in the # hope that it will be useful, but WITHOUT ANY WARRANTY; without even the # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # See the GNU General Public License for more details. # # Main Variables SCRIPTNAME="comp-backup" VERSION=7 LOGNAME="backup_logfile" TARGETNODE="backup.compute.dtu.dk" HOST=$(hostname -s) SERIAL=/etc/dtuserial H=$HOME BIN_DIR="$H/bin" # Banner clear echo "#-------------------------------#" echo "# DTU Compute backup script #" echo "#-------------------------------#" echo echo "This script will setup a backup routine for you" echo "Backup server is: $TARGETNODE" echo # User Specific Variables USER=$(whoami) echo "Enter your DTU username [$USER]:" read ANS case $ANS in "") RUSER=$USER ;; *) RUSER=$ANS ;; esac RHOME=/home/$RUSER SCRIPTNAME="$SCRIPTNAME-$RUSER" # PC Specific Variables echo "Enter the hostname (eg. comp-nbXXXX) [$HOST]:" read ANS case $ANS in "") HOST=$HOST ;; *) HOST=$ANS ;; esac # SUDO chksudo() { echo "Check sudo" sudo -l &>/dev/null if [ $? -ne 0 ]; then echo "You need sudo rights to continue." exit 1 fi echo "[sudo] OK" } # Platform Specific Variables HOST_OS=$(uname -s) if [ $HOST_OS = 'Darwin' ]; then UNIT_DIR="$H/Library/LaunchAgents" [ ! -d $UNIT_DIR ] && mkdir -p $UNIT_DIR CONF_DIR="$H/Library/$SCRIPTNAME" $(which osascript &>/dev/null) if [ $? -eq 0 ]; then NOTIFY0='osascript -e "display notification \"Backup done\" with title \"FYI\""' NOTIFY1='osascript -e "display notification \"Backup did not complete\" with title \"FYI\""' fi pexcl=($H/Movies $H/.Trash $H/Library *.dmg .DS_Store) elif [ $HOST_OS = 'Linux' ]; then CONF_DIR="$H/.config/$SCRIPTNAME" $(which notify-send &>/dev/null) if [ $? -eq 0 ]; then NOTIFY0='notify-send "Backup done"' NOTIFY1='notify-send "Backup did not complete"' fi pexcl=($H/Videos $H/.dbus) # SYSTEMD $(which systemctl &>/dev/null) if [ $? -ne 0 ]; then SYSTEMD=0 echo "No systemd - Backup will need to be run manually" else SYSTEMD=1 # look for 3 digits with a space before and/or after sysd_ver=$(systemctl --version |grep -o '\s[[:digit:]]\{3\}\s\{,1\}') if [ $sysd_ver -lt 220 ]; then echo "No 'systemctl --user' capability" echo "Installing system wide" chksudo dosudo="sudo" UNIT_DIR="/etc/systemd/system" else UNIT_DIR="$H/.config/systemd/user" [ ! -d $UNIT_DIR ] && mkdir -p $UNIT_DIR douser="--user" fi fi else echo "OS not supportet" exit 1 fi incl=($H/) excl=( $H/Downloads $H/Music $H/anaconda* $H/.conda $H/.cache $H/.local $H/.viminfo *.vdi *.vmdk *.iso ) # Initial Setup if [ -x $BIN_DIR/$SCRIPTNAME ]; then ver=$(grep -o [0-9]$ $BIN_DIR/$SCRIPTNAME) if [ $ver -lt $VERSION ]; then echo "New version will be installed" if [ $HOST_OS = 'Linux' ]; then if [ $SYSTEMD = 1 ]; then $dosudo systemctl $douser stop $SCRIPTNAME.timer &>/dev/null $dosudo systemctl $douser disable $SCRIPTNAME.timer &>/dev/null fi fi else echo "Backup script already installed" exit 0 fi elif [ ! -d $BIN_DIR ]; then mkdir $BIN_DIR fi $(echo $PATH | grep -o $BIN_DIR &>/dev/null) if [ $? -ne 0 ]; then if [ $SHELL == '/bin/bash' ]; then echo -e "\nexport PATH=$PATH:$BIN_DIR" >> $H/.bash_profile source $H/.bash_profile elif [ $SHELL == '/bin/zsh' ]; then echo -e "\nexport PATH=$PATH:$BIN_DIR" >> $H/.zprofile source $H/.zprofile else echo -e "\nexport PATH=$PATH:$BIN_DIR" >> $H/.profile source $H/.profile fi fi if [ ! -d $CONF_DIR ]; then mkdir -p $CONF_DIR echo "# Files to include" > $CONF_DIR/include for i in ${incl[*]}; do echo $i >> $CONF_DIR/include done echo "# Files to exclude" > $CONF_DIR/exclude for e in ${excl[*]}; do echo $e >> $CONF_DIR/exclude done for p in ${pexcl[*]}; do echo $p >> $CONF_DIR/exclude done fi # SSH echo "Check ssh" grep $TARGETNODE $H/.ssh/known_hosts &>/dev/null if [ $? -ne 0 ]; then if [ ! -d ~/.ssh ]; then mkdir ~/.ssh chmod 700 ~/.ssh fi ssh-keyscan -H -t ecdsa $TARGETNODE 2>/dev/null|grep ^[^#] >> ~/.ssh/known_hosts fi SSHKEY=~/.ssh/$SCRIPTNAME if [ -f $SSHKEY ]; then ssh -o BatchMode=yes -i $SSHKEY $RUSER@$TARGETNODE "grep -o $USER@$HOST .ssh/authorized_keys" &>/dev/null if [ $? -ne 0 ]; then echo "Installing public key" ssh-copy-id -i $SSHKEY $RUSER@$TARGETNODE &>/dev/null else echo "[ssh] OK" fi else echo "Creating SSH keys" ssh-keygen -q -f $SSHKEY -N '' &>/dev/null ssh-copy-id -i $SSHKEY $RUSER@$TARGETNODE &>/dev/null fi # Create Backup Dir echo "Checking for backup dir..." ssh -i $SSHKEY $RUSER@$TARGETNODE ls -d $RHOME/$HOST &>/dev/null if [ $? = 0 ]; then ssh -i $SSHKEY $RUSER@$TARGETNODE ls $RHOME/$HOST/$LOGNAME &>/dev/null if [ $? = 0 ]; then ssh -i $SSHKEY $RUSER@$TARGETNODE mv $RHOME/$HOST/$LOGNAME $RHOME/$HOST/old_install.$(date +%Y-%m-%d) fi echo "OK" else ssh -i $SSHKEY $RUSER@$TARGETNODE "mkdir $RHOME/$HOST && chmod 700 $RHOME/$HOST" if [ $? = 0 ]; then if [ -f "$SERIAL" ]; then scp -i $SSHKEY $SERIAL $RUSER@$TARGETNODE:$RHOME/$HOST/ &>/dev/null else echo "No Serial file to copy..." fi echo "Created backup dir" else echo "Failed to create backup dir" exit 1 fi fi # Script & Daemon Files echo "Writing files" TMP="$H/.local/tmp" if [ ! -d $TMP ]; then mkdir -p $TMP fi LOG=$TMP/$LOGNAME-$RUSER cat > $BIN_DIR/$SCRIPTNAME << EOF #!/bin/bash # version=$VERSION # Log check logcheck(){ lsize=\$(du $LOG|awk '{print \$1}') if [ \$lsize -gt 2048 ]; then scp -i $SSHKEY $LOG $RUSER@$TARGETNODE:$RHOME/$HOST/$LOGNAME-$RUSER.\$(date +%Y-%m-%d) mv $LOG $LOG.\$(date +%Y-%m-%d) fi } # Main if [ -f $LOG ]; then logcheck fi rsync -arRx -e "ssh -i $SSHKEY" \ --files-from=$CONF_DIR/include \ --exclude-from=$CONF_DIR/exclude \ --delete-excluded --delete-before \ --log-file=$LOG \ / $RUSER@$TARGETNODE:$RHOME/$HOST/ if [ \$? -eq 0 ]; then echo "Backup ok" $NOTIFY0 else echo "Backup failed" $NOTIFY1 fi # Log update rsync -a -e "ssh -i $SSHKEY" $TMP/$LOGNAME-$RUSER $RUSER@$TARGETNODE:$RHOME/$HOST/$LOGNAME EOF chmod +x $BIN_DIR/$SCRIPTNAME if [ $HOST_OS = 'Darwin' ]; then cat > $UNIT_DIR/com.dtucompute.backup.plist << EOF <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>Label</key> <string>com.dtucompute.backup</string> <key>ProgramArguments</key> <array> <string>$BIN_DIR/$SCRIPTNAME</string> </array> <key>StartInterval</key> <integer>10800</integer> </dict> </plist> EOF elif [ $SYSTEMD = 1 ]; then $dosudo bash -c "cat > $UNIT_DIR/$SCRIPTNAME.timer" << EOF [Unit] Description=$SCRIPTNAME timer [Timer] OnBootSec=5min OnUnitActiveSec=3h Unit=$SCRIPTNAME.service [Install] WantedBy=timers.target EOF $dosudo bash -c "cat > $UNIT_DIR/$SCRIPTNAME.service" << EOF [Unit] Description=DTU Compute backup script After=network-online.target Wants=network-online.target [Service] Type=simple ExecStart=$BIN_DIR/$SCRIPTNAME [Install] WantedBy=default.target EOF $dosudo systemctl $douser enable $SCRIPTNAME.timer &>/dev/null fi # Finish echo "Backup script installed" echo