SourceForge VA Linux Systems
Copyright © 2000 Paul Sheer - Click here for copying permissions       Source by FTP

next up previous contents index
Next: Print Server Up: Rute Users Tutorial and Previous: Partitioning, formatting and mounting   Contents   Index

Subsections

Advanced Shell Scripting

Add comments here 

Special parameters: $?, $* etc.

Parameter expansion

Builtin commands

Trapping signals -- the trap command

Internal settings -- the set command

Important environment variables

File locking

Often, one would like a process to have exclusive access to a file. By this we mean that only one process can access the file at any one time. Consider a mail folder: if two processes were to write to the folder simultaneously it could become corrupted. We also sometimes want to ensure that a program can never be run twice at the same time; this is another use for ``locking''.
In the case of a mail folder, if the file is being written to, then no other process should try read it or write to it: and we would like to create a write lock on the file. However if the file is being read from, no other process should try to write to it: and we would like to create a read lock on the file. Write locks are sometimes called exclusive locks, while read locks are sometimes called shared locks. Often exclusive locks are preferred for simplicity.
Locking can be implemented by simply creating a temporary file to indicate to other processes to wait before trying some kind of access. UNIX also has some more sophisticated builtin functions.

Locking a mailbox file

There are currently four methods of file locking23.1
1.
``dot lock'' file locking. Here, a temporary file is created with the same name as the mail folder and the extension .lock added. So long as this file exists, no program should try to access the folder. This is an exclusive lock only. It is easy to write a shell script to do this kind of file locking.
2.
``MBX'' file locking. Similar to 1. but a temporary file is created in /tmp. This is also an exclusive lock.
3.
fcntl locking. Databases require areas of a file to be locked. fcntl is a system call to be used inside C programs.
4.
flock file locking. Same as fcntl, but locks whole files.
The following shell function does proper mailbox file locking:

 
 
 
 
5 
 
 
 
 
10 
 
 
 
 
15 
 
 
 
 
20 
 
 
 
 
25 
function my_lockfile ()
{
        TEMPFILE="$1.$$"
        LOCKFILE="$1.lock"
        { echo $$ > $TEMPFILE } >& /dev/null || {
                echo "You don't have permission to access `dirname $TEMPFILE`"
                return 1
        }
        ln $TEMPFILE $LOCKFILE >& /dev/null && {
                rm -f $TEMPFILE
                return 0
        }
        kill -0 `cat $LOCKFILE` >& /dev/null && {
                rm -f $TEMPFILE
                return 1
        }
        echo "Removing stale lock file"
        rm -f $LOCKFILE
        ln $TEMPFILE $LOCKFILE >& /dev/null && {
                rm -f $TEMPFILE
                return 0
        }
        rm -f $TEMPFILE
        return 1
}

You can include this in scripts that need to lock any kind file as follows:

 
 
 
 
5 
 
 
 
 
10 
# wait for a lock
until my_lockfile /etc/passwd ; do
        sleep 1
done

# The body of the program might go here
# [...]

# Then to remove the lock,
rm -f /etc/passwd.lock

There are a couple of interesting bits in this script: note how the ln function is used to ensure ``exclusivity''. ln is one of the few UNIX functions that is atomic, meaning that only one link of the same name can exist, and its creation excludes the possibility that another program would think that it had successfully created the same link. One might naively expect that the program,

 
 
 
 
5 
 
 
function my_lockfile ()
{
        LOCKFILE="$1.lock"
        test -e $LOCKFILE && return 1
        touch $LOCKFILE
        return 0
}

is sufficient for file locking. However consider if two programs running simultaneously executed line 4 at the same time. Both would think that the lock did not exist and proceed to line 5. Then both would successfully create the lockfile -- not what you wanted.

The kill command is then useful for checking if a process is running. Sending the 0 signal does nothing to the process, but fails if the process does not exist. This can be used to remove a lock of a process that died before doing so itself: i.e. a stale lock.

Locking over NFS

The above script does not work if your file system is mounted over NFS (networked file system -- see Chapter 29). This is obvious because it relies on the PID of the process, which could clash across different machines. Not so obvious is that the ln function does not work exactly right over NFS -- you need to stat the file and actually check that the link count has increased to 2.
There is a program that comes with the procmail package called lockfile and another that comes with the mutt email reader called mutt_dotlock (perhaps not distributed). These do similar file locking, but do not store the PID in the lock file. Hence it is not possible to detect a stale lock file. For example to search your mailbox, you can do:

 
 
 
lockfile /var/spool/mail/mary.lock
grep freddy /var/spool/mail/mary
rm -f /var/spool/mail/mary.lock

which will ensure that you are searching a clean mailbox even if /var is a remote NFS share.

Directory versus File locking

File locking is a headache for the developer. The problem with UNIX is that whereas we are intuitively thinking about locking a file, what we really mean is locking a file name within a directory. File locking per se should only be used on perpetual files, such as database files. For mailbox and passwd files we need directory locking23.2, meaning the exclusive access of one process to a particular directory entry. In my opinion, lack of such a feature is a serious deficiency in UNIX, but because it will require kernel, NFS, and (possibly) C library extensions, will probably not come into being any time soon.

Locking inside C programs

This certainly outside of the scope of this text, except to say that you should consult the source code of reputed packages rather than invent your own locking scheme.

next up previous contents index
Next: Print Server Up: Rute Users Tutorial and Previous: Partitioning, formatting and mounting   Contents   Index
Paul Sheer 2000-10-07