Automating frequent tasks

Useful routines

The following routines are not entire scripts, but may be useful in context.

Locking files

It is sometimes necessary to use a shell script that controls access to a shared resource; for example, a file which should only be written by one person at a time. The following skeleton code shows an appropriate wrapper for such a script:

   trap "exit 1" 1 2 3 15
   # trap is vital, otherwise we may loop infinitely
   umask 777
   until > $LOCKFILE
     sleep 1
   done 2> /dev/null
   umask $OMASK
   # now we can write critical data safely, unless root
   # finished critical section
   rm -f $LOCKFILE
The user's old umask value is saved in OMASK, and their umask is reset to 777; this means that any files the user creates will have no read, write or execute permissions.

LOCKFILE is the name (determined elsewhere in the script) of a lock file. While a lock file exists, only the owner of the file should be allowed to operate on the shared data. This is ensured by the until loop:

   until > ${LOCKFILE}
     sleep 1
   done 2> /dev/null
The value of until only becomes TRUE when it can create a lockfile; this can only happen when no other users of the script have created a lock. (The lock has no write permission for anyone other than its creating process.) If this condition is true, the script creates the empty ${LOCKFILE} and continues; if false, it sleeps for a second and tries again. Having acquired the lockfile, the script resets umask to the user's original file creation permissions.

Having acquired a lock file, it is now certain that anyone else trying to run the script at the same time will get as far as the loop but no further; it is therefore safe to work on the shared resource, knowing that nobody else is simultaneously using it and might accidentally overwrite the user's changes. After using the shared resource, it is important to delete the lockfile; if the lock file is left behind, nobody will be able to access the shared resource.

This kind of access locking is typically used to control databases or critical applications where it is unsafe to risk a race condition (where two processes try to update a shared resource concurrently, overwriting each other's changes).

Next topic: Context sensitive scripts
Previous topic: Compress a batch of files concurrently

© 2003 Caldera International, Inc. All rights reserved.
SCO OpenServer Release 5.0.7 -- 11 February 2003