help-bash
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Question] Reliable way to clean up a directory in EXIT trap


From: Masahiro Yamada
Subject: [Question] Reliable way to clean up a directory in EXIT trap
Date: Tue, 19 Jul 2022 02:15:38 +0900

Hi.

I am searching for a reliable way to clean up a temporary directory
from a bash script.



In my bash script, I run a command that creates some intermediate files
in a temporary directory.

I want to clean up the temporary directory when the bash script exits,
not only when it finishes normally, but also when it is interrupted by Ctrl-C.

I think using the EXIT trap is a simple way, but it misses
to delete the temporary directory sometimes.

I want to know why, and a better solution.


Please see the following simple test scripts.


----------------------(begin of test2.sh)------------------------------
#!/bin/bash
set -e

# use .tmp_<PID> as a temporary workspace
TMPDIR=.tmp_$$

trap "rm -rf $TMPDIR" EXIT

mkdir -p $TMPDIR
touch $TMPDIR/tmp
----------------------(end of test2.sh)------------------------------


----------------------(begin of test.sh)--------------------
#!/bin/bash

i=0
while [ $i -lt 1000 ]; do
        ./test2.sh
        i=$(( i + 1 ))
done
----------------------(end of test.sh)--------------------



If I run ./test.sh normally, I do not see any tmp directory left-over.


masahiro@grover:/tmp/foo$ ls -a
.  ..  test2.sh  test.sh
masahiro@grover:/tmp/foo$ ./test.sh
masahiro@grover:/tmp/foo$ ls -a
.  ..  test2.sh  test.sh




Run './test.sh' and immediately hit Ctrl-C.
Repeat this several times.



masahiro@grover:/tmp/foo$ ls -a
.  ..  test2.sh  test.sh
masahiro@grover:/tmp/foo$ ./test.sh
^C
masahiro@grover:/tmp/foo$ ./test.sh
^C
masahiro@grover:/tmp/foo$ ./test.sh
^C
masahiro@grover:/tmp/foo$ ./test.sh
^C
masahiro@grover:/tmp/foo$ ./test.sh
^C
masahiro@grover:/tmp/foo$ ./test.sh
^C
masahiro@grover:/tmp/foo$ ./test.sh
^C
masahiro@grover:/tmp/foo$ ls -a
.  ..  test2.sh  test.sh  .tmp_1997953



I see a tmp directory left-over.




The following is what I understand.
(Please correct me if I am wrong)



[1]
POSIX does not clearly define the conditions resulting in executing
the EXIT trap.
In bash, the EXIT trap is invoked when the script is exiting,
including when it is
caused by SIGINT or SIGTERM.

This is not necessarily true for other shells.
For example, dash does not invoke the EXIT trap when the script is exiting
due to SIGINT or SIGTERM


[2]
When you hit Ctrl-C, SIGINT is sent to all the processes in the process group
being executed fore-ground.

In the example above, SIGINT is sent to the interactive shell,
test.sh, test2.sh, and mkdir or touch if it is running.



[3]
Bash (and many other shells) does not immediately handle SIGINT
if it is running another foreground process.
When receiving SIGINT, Bash just _remembers_ the fact that it has
received SIGINT.
After the foregound process finishes, Bash handles the signal.

In the example above,
test2.sh waits until 'mkdir' or 'touch' finishes if it is running on
receiving SIGINT.
After 'mkdir' or 'touch' finishes, test2.sh handles the INT signal.
SIGINT is not overridden. The default behavior is to terminate the script.
It executes "rm -rf $TMPDIR" before the exit.



With [1], [2], [3] in my mind, I cannot find the condition
when the tmp directory is left over.




What am I missing?


-- 
Best Regards
Masahiro Yamada



reply via email to

[Prev in Thread] Current Thread [Next in Thread]