Home > Software engineering >  Make Bash Script Recognize It Is Already Existent
Make Bash Script Recognize It Is Already Existent

Time:08-24

Question
How can I instruct my the bash script to not attempt to re-connect if to my rsync daemon if the process lock.file already exists? (as to prevent the bash script from attempting to infinitely create new connections after the first connection has already been made)?

This is an example of one of my rsync-daemon wrapper scripts:

#!/bin/sh
#
#
while [ 1 ]
do

   cputool --load-limit 7.5 -- nice -n -15 rsync -avxP --no-i-r --rsync-path="rsync" --log-file=/var/log/rsync-home.log --exclude 'snap'  --exclude 'lost found' --exclude=".*" --exclude=".*/" 127.0.0.1::home /media/username/external/home-files-only && sync && echo 3 > /proc/sys/vm/drop_caches
   
    if [ "$?" = "0" ] ; then
        echo "rsync completed normally"
        exit
    else
        echo "Rsync failure. Backing off and retrying..."
        sleep 10
    fi
done

#end of shell script

This is my /etc/rsyncd.conf:

[home]
path = /home/username
list = yes
use chroot = false
strict modes = false
uid = root
gid = root
read only = yes
# Data source information
max connections = 1
lock file = /var/run/rsyncd-home.lock

[prod-bkup]
path = /media/username/external/Server-Backups/Prod/today
list = yes
use chroot = false
strict modes = false
uid = root
gid = root
# Don't allow to modify the source files
read only = yes
max connections = 1
lock file = /var/run/rsyncd-prod-bkup.lock

[test-bkup]
path = /media/username/external/Server-Backups/Test/today
list = yes
use chroot = false
strict modes = false
uid = root
gid = root
# Don't allow to modify the source files
read only = yes
max connections = 1
lock file = /var/run/rsyncd-test-bkup.lock

[VminRoot2]
path = /root/VDI-Files
list = yes
use chroot = false
strict modes = false
uid = root
gid = root
# Don't allow to modify the source files
read only = yes
max connections = 1
lock file = /var/run/rsyncd-VminRoot2.lock

CodePudding user response:

Thanks to @james-brown I now have multiple ways to ensure my script runs once.. correctly...

Solution 1 (quick & dirty):

flock -n <lock file> <script>

Or in my case, using this command to execute my cron job:

flock -n /var/run/rsyncd-home.lock /path/to/my_script.sh

caveat - this leaves your script vulnerable to stale lock files that may prevent execution on the next time interval.

Solution 2:
So, I used a bullet-proof method (so I think... I invite folks to correct my understanding, if need be)...

First, I did apt install procmail, then removed/hashed out the below two lines in my /etc/rsyncd.conf and ran systemctl restart rsync:

#max connections = 1
#lock file = /var/run/rsyncd-home.lock

From there I edited /usr/local/bin/backupscript.sh as follows:

#!/bin/bash
#
LOCK=/var/run/rsyncd-home.lock
remove_lock()
{
    rm -f "$LOCK"
}
another_instance()
{
    echo "There is another instance running, exiting"
    exit 1
}
lockfile -r 0 -l 3600 "$LOCK" || another_instance
trap remove_lock EXIT

#new using rsyncd & perpetual restart
while [ 1 ]
do
   cputool --load-limit 7.5 -- nice -n -15 rsync -avxP --no-i-r --rsync-path="rsync" --log-file=/var/log/rsync-home.log --exclude 'snap'  --exclude="Variety Images" --exclude="Downloads/WebDev/Vmin-Vbox" --exclude 'Downloads/WebDev/Win10-Vbox'  --exclude="Videos/other" --exclude 'lost found' --exclude=".*" --exclude=".*/" 127.0.0.1::home /media/username/external/home-files-only && sync && echo 3 > /proc/sys/vm/drop_caches
   
    if [ "$?" = "0" ] ; then
        echo "rsync completed normally"
        exit
    else
        echo "Rsync failure. Backing off and retrying..."
        sleep 10
    fi
done

#end of shell script

PRESTO:
The script will only connect to rsync daemon once, it will re-connect on dropped connections thanks to the while loop, and there is no danger of stale lock files interrupting my backup process at future intervals... (i.e. problem solved).

Very useful reference: https://www.baeldung.com/linux/bash-ensure-instance-running

  • Related