Pro Backup
Pro Backup

Reputation: 761

How to ensure that only one instance of a busybox shell script is running at a time without lock(file)?

In a router with a rather limited Busybox (version 1.24.2) shell I want to make sure that a backup (rsync) shell script only executes when it is not already running.

The answers for a full blown Bash shell as in:

  1. Quick-and-dirty way to ensure only one instance of a shell script is running at a time
  2. Shell script: Ensure that script isn't executed if already running

are not compatible with the crippled Busybox ash shell.

The router firmware supplies these busybox commands:

[, [[, addgroup, adduser, arp, arping, ash, awk, basename, bash, brctl, bunzip2, bzcat, bzip2, cat, chgrp, chmod, chown, chpasswd, chroot, clear, cp, crond, crontab, cut, date, dd, df,
dhcp6c, dirname, dmesg, dnsdomainname, dos2unix, du, echo, egrep, eject, env, ether-wake, expr, false, fdisk, fgrep, find, flock, free, fuser, grep, gunzip, gzip, head, hostname,
ifconfig, inetd, insmod, kill, killall, klogd, ln, logger, login, ls, lsmod, lsof, md5sum, mdev, microcom, mkdir, mknod, mkswap, modprobe, more, mount, mountpoint, mv, netstat, nice,
nslookup, ntpd, passwd, pgrep, pidof, ping, ping6, printf, ps, pwd, rm, rmdir, rmmod, route, sed, sendmail, seq, sh, sleep, sort, start-stop-daemon, stat, strings, swapoff, swapon,
switch_root, sync, sysctl, syslogd, tail, tar, tee, telnetd, test, time, top, touch, tr, traceroute, traceroute6, true, udhcpc, umount, uname, uniq, unix2dos, unlink, uptime, usleep,
vconfig, vi, watch, wc, wget, which, whoami, xargs, yes, zcat, zcip 

The flock self-invocation solution does return exit 1 upon first invocation. Used test script:

#!/bin/sh
[ "${FLOCKER}" != "$0" ] && exec /usr/bin/env FLOCKER="$0" /usr/bin/flock "$0" "$0" "$@" || exit 1
echo "servus!"
/bin/sleep 30

The ps suggestion from an answer at https://unix.stackexchange.com/questions/48505/how-to-make-sure-only-one-instance-of-a-bash-script-runs#answer-48511 is promising but still not compatible with a router reduced Busybox shell. Busybox comes with the ps command, but only with options w, l and T.

Any suggestions, not catching nano or another editor with this script open?

Upvotes: 2

Views: 1878

Answers (2)

stux
stux

Reputation: 2986

This is straight out of the flock manpage, BUT the -e "exclusive" flag has been replaced with -x, which is a synonym supported by busybox.

#!/bin/sh
# ensure script only runs exclusively, additional invocations return immediately
[ "${FLOCKER}" != "$0" ] && exec env FLOCKER="$0" flock -xn "$0" "$0" "$@" || :

Seems to work as expected. See flock man page for further info.

Upvotes: 1

Pro Backup
Pro Backup

Reputation: 761

flock seems necessary to not create a race condition. A flock based solution that works with busybox 1.24.2:

#!/bin/bash

scriptname=$(basename $0)
lock="/var/run/${scriptname}"

exec 200>$lock
flock -n 200 || { echo "Error: Another copy of $0 is running. Exiting" ; exit 1; } 

pid=$$
echo $pid 1>&200

## Sample code
sleep 60
echo "Hello world"

source: https://linuxaria.com/howto/linux-shell-introduction-to-flock

Upvotes: 0

Related Questions