home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #16 / NN_1992_16.iso / spool / comp / unix / shell / 3115 < prev    next >
Encoding:
Internet Message Format  |  1992-07-24  |  4.4 KB

  1. Xref: sparky comp.unix.shell:3115 comp.unix.programmer:3887
  2. Path: sparky!uunet!zaphod.mps.ohio-state.edu!sol.ctr.columbia.edu!eff!snorkelwacker.mit.edu!ai-lab!life.ai.mit.edu!friedman
  3. From: friedman@gnu.ai.mit.edu (Noah Friedman)
  4. Newsgroups: comp.unix.shell,comp.unix.programmer
  5. Subject: Re: file locking in shell scripts
  6. Message-ID: <FRIEDMAN.92Jul24055302@nutrimat.gnu.ai.mit.edu>
  7. Date: 24 Jul 92 09:53:02 GMT
  8. References: <1992Jul23.124327.20843@cv.ruu.nl>
  9. Sender: news@ai.mit.edu
  10. Followup-To: comp.unix.shell
  11. Organization: Free Software Foundation, 675 Mass Ave. Cambridge, MA 02139
  12. Lines: 75
  13. In-reply-to: rvloon@cv.ruu.nl's message of 23 Jul 92 12:43:27 GMT
  14.  
  15. In article <1992Jul23.124327.20843@cv.ruu.nl> rvloon@cv.ruu.nl (Ronald van Loon) writes:
  16. >Somewhere on our system is a log-file. This logfile is used to gather
  17. >statistical information. However, it is possible that people write to the file
  18. >at the same time, thus resulting in either the merge of the input-streams or
  19. >total garbage in the file.
  20. >
  21. >How can I - within a shell script - lock the file exclusive for writing ? If
  22. >that's not possible, what do I need to use to do so from C, for example ?
  23.  
  24.    If you can design the locking protocol yourself, and make sure that
  25. every interface people will use to write the log file will follow that
  26. protocol, you can specify when a file is locked by creating a separate
  27. lockfile.  Other programs seeing this file will know someone else has a
  28. lock on the log file (many mail programs use this "advisory" locking
  29. method).  You can easily create a lock file in a C program using
  30.  
  31.             open (lockfile_path, O_CREAT|O_EXCL|..., mode);
  32.  
  33. (appropriate error checking omitted, since that part is obvious).  This
  34. means that open will only create the file if it does not already exist.
  35. This is an atomic operation, so you shouldn't have to worry about any race
  36. conditions (locally, anyway.. I don't know if anything is guaranteed over
  37. NFS, including other locking methods!)
  38.  
  39.    So the question is, do any shells provide a way of doing this
  40. sort of exclusive creation?  None of them that I could get the source code
  41. to.  So if you want reliability, don't do it in shell script.  I'm going to
  42. suggest a patch to bash that will make the noclobber feature a little more
  43. reliable (it presently does a stat and then an open, which results in a
  44. race condition), and then it will be possible to do the following safely:
  45.  
  46.             set -o noclobber
  47.             lockp=$( (> lockfile) 2>&1)
  48.  
  49.             if [ -z "${lockp}" ]; then
  50.                # acquired the lock
  51.             else
  52.                # Did not acquire the lock---either can't create the file
  53.                # because we don't have permission, or the file already
  54.                # exists and someone else has a lock.  These two conditions
  55.                # are possible to distinguish by doing a series of "test"
  56.                # commands on the file or directory in which you wished to
  57.                # create it, although there may be a race condition in which
  58.                # the lock file has been removed in between tests.
  59.                # You can also try the more shaky method of examining the
  60.                # contents of $lockp.. if it says "Cannot clobber existing
  61.                # file" or whatever, you can probably guess what happened. 
  62.                # In C you could just look at errno (== EEXIST). 
  63.             fi
  64.  
  65. This relies on bash printing an error message on stderr when it refuses to
  66. clobber a file.  I did it this way becase bash (as of version 1.12) has a
  67. bug: it doesn't return a nonzero exit status when it refuses to clobber
  68. files (yes, I've told the maintainers about this too).  In a
  69. properly-working version (hopefully 1.13) you should be able to just do:
  70.  
  71.              set -o noclobber
  72.              if 2> /dev/null > lockfile ; then
  73.                 # acquired the lock
  74.              else
  75.                 # didn't acquire the lock
  76.              fi
  77.  
  78. This is at least one way to (almost) do locking in pure shell script.  I
  79. suspect other methods are probably more difficult, if not also presently
  80. impossible.  However, you can write a small C program to do the atomic
  81. exclusive file creation, returning an exit status that indicates whether it
  82. succeeded or failed.  Then the rest can probably be done in shell script
  83. (depending on what else you want to do, that is).
  84.  
  85.    Tom or Larry: can perl do this correctly?
  86.  
  87.  
  88. (PS: note that these examples don't work in zsh either, because zsh has
  89. even more bugs than bash does with regards to file clobbering)
  90.