views:

1250

answers:

5

I am creating temporary files from a bash script. I am deleting them at the end of the processing, but since the script is running for quite a long time, if I kill it or simply CTRL-C during the run, the temp files are not deleted.
Is there a way I can catch those events and clean-up the files before the execution ends?

Also, is there some kind of best practice for the naming and location of those temp files?
I'm currently not sure between using:

TMP1=`mktemp -p /tmp`
TMP2=`mktemp -p /tmp`
...

and

TMP1=/tmp/`basename $0`1.$$
TMP2=/tmp/`basename $0`2.$$
...

Or maybe is there some better solutions?

+8  A: 

You could set a "trap" to execute on a control-c to clean up.

Alternatively, one of my favourite unix-isms is to open a file, and then delete it while you still have it open. The file stays on the file system and you can read and write it, but as soon as your program exits, the file goes away. Not sure how you'd do that in bash, though.

BTW: One argument I'll give in favour of mktemp instead of using your own solution: if the user anticipates your program is going to create huge temporary files, he might want set "TMPDIR" to somewhere bigger, like /var/tmp. mktemp recognizes that, your hand-rolled solution (second option) doesn't. I frequently use "TMPDIR=/var/tmp gvim -d foo bar", for instance.

Paul Tomblin
ephemient
Accepted you answer since the link you provided is what explains the best what I needed. Thanks
skinp
A: 

You don't have to bother removing those tmp files created with mktemp. They will be deleted anyway later.

Use mktemp if you can as it generates more unique files then '$$' prefix. And it looks like more cross platform way to create temp files then explicitly put them into /tmp.

Mykola Golubyev
Deleted by whom or what?
innaM
Deleted by operation|file system itself after some period of time
Mykola Golubyev
Magic? A cronjob? Or a rebooted Solaris machine?
innaM
Probably one of them. If temp file wasn't removed by some interruption ( it won't be too often ) someday tmp files will be removed - that's why they called temp.
Mykola Golubyev
You can not, should not, must not assume that something put in /tmp will remain there forever; at the same time, you should not assume that it will magically go away.
innaM
+5  A: 

You want to use the trap command to handle exiting the script or signals like CTRL-C. See the Advanced Bash Scripting Guide for details.

For your tempfiles, using basename $0 is a good idea, as well as providing a template that provides room for enough temp files:

tempfile() {
    tempprefix = $(basename "$0")
    mktemp /tmp/${tempprefix}.XXXXXX
}

TMP1 = $(tempfile)
TMP2 = $(tempfile)

trap 'rm -f $TMP1 $TMP2' EXIT
Brian Campbell
Do not trap on TERM/INT. Trap on EXIT.Trying to predict the exit condition based on signals received is silly and definately not a catchall.
lhunath
Minor point: Use $() instead of single backticks. And put double quotes around $0 because it could contain spaces.
Aaron Digulla
Well, the backticks work fine in this comment, but that's a fair point, it is good to be in the habit of using `$()`. Added the double quotes as well.
Brian Campbell
+11  A: 

I usually create a directory in which to place all my temporary files, and then immediately after, create an EXIT handler to clean up this directory when the script exits.

TMPDIR=`mktemp -d`
trap "rm -rf $TMPDIR" EXIT

If you put all your temporary files under $TMPDIR, then they will all be deleted when your script exits in most circumstances. Killing a process with SIGKILL (kill -9) kills the process right away though, so your EXIT handler won't run in that case.

Chris AtLee
+1 Definately use a trap on EXIT, not silly TERM/INT/HUP/whatever else you can think of.Though, remember to **quote** your parameter expansions and I would *also* recommend you *single* quote your trap:trap 'rm -rf "$TMPDIR"' EXIT
lhunath
Single quotes, because then your trap will still work if later on in your script you decide to clean up and change TMPDIR because of circomstances.
lhunath
Minor point: Use $() instead of single backticks.
Aaron Digulla
A: 

The alternative of using a predictable file name with $$ is a gaping security hole and you should never, ever, ever think about using it. Even if it is just a simple personal script on your single user PC. It is a very bad habit you should not obtain. BugTraq is full of "insecure temp file" incidents. See here, here and here for more information on the security aspect of temp files.

I was initially thinking of quoting the insecure TMP1 and TMP2 assignments, but on second thought that would probably not be a good idea.

hlovdal