Backup Files to Github using Cron and Shell script

When you want to backup your files on computers every day/week/month, you can use backup software. In addition to those, I do the way to rely on Github when save arbitrary files. For example, a config file for some app, a daily memo markdown file or setting.json of VScode etc.

In this post, I would share an idea to backup any specific files to your github repository. The point is that you can back up even one file for any folders.

Steps

  • Create a Github repository and local repository.

  • Specify files to backup.

  • Cron triggers the shell script.

  • The shell script checks if the files are updated. If so, copy overwrite them to the local repository.

  • Push to github repository.

Prerequisites

We need these or alternatives:

  • unix, shell, cron

  • Github account

Create Local and Remote repository

Create a repository and setup to connect with CLI.

Important Note: the repository should be private.

Creating a personal access token (with permission “repo: Full control of private repositories”) would be secure. Put the token in you .env file.

MY_TOKEN=<personal access token>

Create shell script

Create a shell script file, with a name cron_git_arbitray_file.sh for example. Put it in the same directory as .env.

Paste the script below.

Parameters to set are like this. List is a list of files to be backed up. REMOTE_REPO is github repository, LOCAL_REPO is where local repository. SUBDIR_REPO is optional to use subdirectory under REMOTE_REPO. Set USERNAME and PASSWORD for github name and token.

#!/bin/bash

# Back up specific files on any directories.
# Using cron job, check update for each file.
# Up-to-date files are copied to local repository
# and pushed to github.
#
# Usage: 
#   $ bash ./cron_git_arbitray_file.sh
# cron example. execute at every 4am: 
#   0 4 * * * (cd /home/dir/of/sh/ && bash cron_git_arbitrary_file.sh)
# Log: ./log/yyyymmdd.log is saved.

#
# Parameters
# ----------
# declare -a List=(
#   "/home/user/full/path/to/file.file"
#   "/home/user/.config/path/to/file.file"
# )
# REMOTE_REPO="github.com/username/reponame.git"
# LOCAL_REPO="/home/user/local/reponame/"
# SUBDIR_REPO="sub-dir-in-repo/" # optional
# USERNAME="github-username"
# PASSWORD="password-token"
# ----------

# Set files to auto backup
declare -a List=(
  "/home/user/full/path/to/file.file"
  "/home/user/.config/path/to/file.file"
)

source ./.env
REMOTE_REPO="github.com/username/reponame.git"
LOCAL_REPO="/home/user/local/reponame/"
SUBDIR_REPO="sub-dir-in-repo/" # optional
USERNAME="github-username"
PASSWORD=$MY_TOKEN

# <dir_of_sh>/log/YYYYMMDD.log is created.
PWD=$(pwd)
log_file=$PWD"/log/$(date +%Y%m%d).log"
mkdir -p $PWD"/log" && touch $log_file

# confirm SUBDIR_REPO exists
mkdir -p $LOCAL_REPO$SUBDIR_REPO

# main
echo "----- $(date +%Y/%m/%d-%H:%M:%S): $(basename "$0") -----" >>$log_file
cd $LOCAL_REPO
update_cnt=0

# check update for each item
for item in "${List[@]}"; do

  # full/path/file to full_path_file
  filename_full=$SUBDIR_REPO"${item//\//_}"

  file1=$item
  file2=$LOCAL_REPO$filename_full
  echo "Update check: "$file1 >>$log_file

  command1="date +%Y%m%d%H%M%S -r "$file1
  command2="date +%Y%m%d%H%M%S -r "$file2

  a=$(eval $command1)
  b=$(eval $command2)

  if [[ $a -eq $b ]]; then

    echo "  No update." >>$log_file

  else

    echo "  Found update. Copy it to local repo. Git add, commit, push." >>$log_file

    ((update_cnt = update_cnt + 1))

    cp -p $file1 $file2

    $(eval "git add "$file2)

  fi
done

if [[ $update_cnt -gt 0 ]]; then
  git commit -m "Automatic back up"
  git push -u https://$USERNAME:$PASSWORD@$REMOTE_REPO master >/dev/null 2>&1
fi

Logging In the script above, log files are created in log/ with a name like :

----- 2023/07/28-07:18:08: cron_git_arbitrary_file.sh -----
Update check: /home/user/.config/Code/User/settings.json
No update.
Update check: /home/user/Desktop/backup/cron_git_arbitrary_file.sh
Found update. Copy it to local repo. Git add, commit, push.

This is just redirecting echo "XXXX" >>$log_file . Create cron Write in your crontab like this.

0 4 * * * (cd /home/dir/of/sh/ && bash cron_git_arbitrary_file.sh)

cd /home/dir/of/sh/ is for changing directory for logging.

I have shown how to push specific files to the Github repository to backup. The script can run automatically using cron.

If this post was helpful, please do follow and click the clap 👏 button below to show your support.

Follow me on Linked-in for further updates-

/ https://www.linkedin.com/in/sushantkapare/