Post

Backup local Data to external drive bash script

I wanted to automate local machine data backup to external drive. First I was checking is there somekind of backup solutions already but then I thought it might be better to practice my bash scripting skills which are not good say the least.

Logic

  1. Mount external drive
  2. Copy every specified folder to external drive as TAR file
  3. cleanup “old” TAR-files
  4. unmount external drive

The Importance of Unmounting
Failure to unmount before disconnecting the device can result in loss of data and/or a corrupted file system.

Here’s a walkthrough of my creation. Full script can be found here

Functions & configs

Functions

First part of the script contains functions which I needed

1
2
3
4
5
6
7
8
9
10
11
12
13
# Function, Define a timestamp
function timestamp() {
          local NOW=$(date +"%Y-%m-%d-%H-%M-%S") # current time
          echo $NOW
}

# Function, create filename
function createFileName(){
          local parameter=$1
          local now=$(timestamp)
          local fileName="$parameter-$now"
          echo $fileName
}

With these functions I can create file name with time stamps. The format I wanted to have is name-YYYY-MM-DD-HH-MM-SS

timestamp() doesn’t take any parameters, it just creates current time as YYYY-MM-DD-HH-MM-SS

createFileName() takes one parameter and sets it to parameter-variable. This is due to my lack of bash understanding and $1 just seems to be too confusing currently. Function gets timestamp from timestamp-function to now-variable. Both variables are combined to fileName-variable. createFile-function is called from main section when creating backup file name.

I know I could have combined those two functions in to one but it is what it is.

Configs

1
2
3
4
5
6
7
8
9
10
11
# CONFIGS
FoldersToBackup=(
"/PathToFolder/folder1"
"/PathToFolder/folder2"
"/PathToFolder/folder3"
)

# Get device path by using sudo fdisk -l
Device="/dev/sdb1"
# Destination where device is mounted and files are copied
Destination="/media/external-backup"

There’s simple array with full paths of folders which needs to be backed up. I was thinking maybe I could create object array which contains folder path and name for each folder. With this way I could give a custom backup name if I wanted to. But then I realized this is too advanced for me right now. Let’s keep it simple for now.

There’s also basic variables for mounting/unmounting the drive.

IMPORTANT create /media/external-backup location before running the script.

sudo mkdir /media/external-backup

Main script

Mount backup location as active

1
2
echo "Mounting drive "$Device "to" $Destination
sudo mount -t ntfs-3g $Device $Destination

I’m using external hard drive which is formated to ntfs due to my need to use it on windows machines without any problems.

Create backups

1
2
3
4
5
6
7
8
echo "Starting backup operation"
for sourcePath in ${FoldersToBackup[@]}; do
          folderName=$(basename $sourcePath)
          FileName=$(createFileName "$folderName")
          destinationPath=$Destination"/"$FileName".tar.gz"
          sudo tar -zcvf $destinationPath $sourcePath
          echo $destinationPath
done

Just a simple for-loop to read FoldersToBackup-array. I’m exctracting folder name by using basename to folderName-variable. FileName variable is getting return value from createFileName-function to which I pass folderName-variable. FileName should be something like folder1-2023-02-12-18-01-15 destinationPath variable is created by using Destination and FileName variables. then compress source folder to destination location with tar command z = Use gzip c = Create a new archive. v = List the name of each file as it is processed f = Next argument is file name of the archive (or destination path)

Also for debugging this command list contents of .tar.gz file tar -tvf /media/external-backup/folder1-2023-02-12-18-01-15 t = List files v = List the name of each file as it is processed f = Next argument is file name of the archive (or full path)

Cleanup backups

1
2
3
4
#Delete old files
echo Cleaning up old backups
find $Destination -name "*.tar.gz" -type f -mtime +60 -delete
ls -lah $Destination

Using find command to find all files ending with .tar.gz from destination location, filter out all recent backups and deleting old backups.
name = every file ending .tar.gz type f = Restrict find to just files mtime +60 = Filter out everything newer than 60 days ago modified files delete = delete results which are returned from previous filtering

Unmount drive

1
2
echo "Unmounting" $Destination
sudo umount $Device

Nothing fancy just unmounting operation

docs

Usefull information about mounting: https://kenfavors.com/code/mounting-an-external-drive-on-ubuntu-server/

This post is licensed under CC BY 4.0 by the author.