Standard Mischief

common bash misconception

If you’ve done any bash shell scripting, you may have come across the need to write data to a temporary file. However, a well-written script should take in the possibility that it will be run more than once at the same time, (the unices being multi-tasking and all that), so you will want to make sure that different processes don’t all write the same data to the same hard-coded /tmp file.

One of the standard ways to do this is to use the bash built-in variable “$$“, like so:

echo $data-to-log >> /tmp/"$$"log.file.txt

And that usually works fine, as long as only one person is running that script per login account. You will, however, have issues if you run the script from the console at the same time that the script is run from your crontab. Ask me how I know.

The common misconception here is the idea that the bash built-in variable$$holds the PID (process ID) of the script itself. That is not true. It’s actually the PID of your bash shell. Therefore running your carefully crafted script more than once at the same time can fsck-up your script output.

A better way, and my standard mischief, is to do the following. First, somewhere up near the top of your shell script create a variable that is unique, like so:

uq=$(date +%s-%N)

backtick people can use this:

uq=`date +%s-%N`

but I like to use the “$()” out of habit because it makes it easier to nestle the commands. Besides, after too much caffeine and staring at a LCD all day, those backticks can be a bit hard to see.

Then, we use this variable in place of “$$“, like so:

echo $data-to-log >> /tmp/"$uq"log.file.txt

What we are doing here is running the date command, and having it show the number of seconds since the Unix epoch back in 01jan1970. Then, we add a dash and the number of nanoseconds. We assign the results of that command to the variable “$uq“. The end result is that unless the two scripts run this command at exactly the same time (probably impossible even if you were trying), the variable $uq is going to be a wholly unique number. When you use this unique number in a filename you can be pretty sure you won’t be clobbering existing data by overwriting an existing file.


2009-03-25 06:35 by Standard Mischief, Filed under:don't try this at home   2 Comments »

Comments

  1. jonathan Franzone Says :

    Good point! My article actually used the fact that is was NOT unique in order to detect whether or not the script was already running.

    If you are trying to output unique temporary files you could also look into using the mktemp command.

    2009-03-25 10:35 Permalink
  2. Standard Mischief Says :

    Sorry, I used curl to download a bunch of likely pages and then used grep to look for “$$”

    Thanks for the tip on mktemp. I didn’t know that command.

    I like using the unix time stamp because date-stamping your temp files can be useful for troubleshooting. Also, if sorted by filename they end up in chronological order.

    2009-03-25 21:44 Permalink

Leave a comment

(required)

(required)

RSS feed for comments on this post. TrackBack URL

current.png

Powered by WordPress , Theme Ported to Wordpress by Liu Xun. Original Design by Cathayan