1

Calling a function in a script in background - using '&', the function is called in a subshell. When the function ends, the subshell ends, with an exit status. I would like to trap the exit signal of such subshell to automatically cancel log files. My testing script is as follow:

$ cat mscript.sh 
#!/usr/bin/env sh

mout="log.out"
rm -f $mout

# My testing log files
tmps=(first.tmp second.tmp third.tmp)

# Traps exit signal to delete the logfile upon exiting.
mtrap_tmp() {
  local ftmp="$1"
  # I create the tep file here:
  echo "init $ftmp" &>> $ftmp
  echo -e "\n($BASHPID) trapping \"$ftmp\"..." &>> $mout
  ## Here I trap the signal, to delete the temporary file.
  trap "rm -f \"$ftmp\"" EXIT
  echo -e "  trapped tmp file \"$ftmp\" to rm" &>> $mout
  echo "  $(ls -l $ftmp)" &>> $mout
}

# I trap the first and second log files within the script's pid. 
# Then I trap the third file in a subshell:
mtrap_tmp ${tmps[0]}
mtrap_tmp ${tmps[1]}
mtrap_tmp ${tmps[2]} &
wait $!

# Here I want to check the temp files do exist. 
# I expect the third file to be trapped in a subshell, 
# and hence to be non-existent once the subshell ends, 
# which should have happened after the `wait $!`:

for i in ${tmps[@]}; do
  echo -e "\nfinal check $i:" &>> $mout
  ls -l ${i} &>> $mout
done

echo "done"
exit 0 

The output is as follow:

$  cat log.out 

(10598) trapping "first.tmp"...
  trapped tmp file "first.tmp" to rm
  -rw-rw-r-- 1 anadin ctgb 15 Jul  4 15:54 first.tmp

(10598) trapping "second.tmp"...
  trapped tmp file "second.tmp" to rm
  -rw-rw-r-- 1 anadin ctgb 16 Jul  4  2017 second.tmp

(10602) trapping "third.tmp"...
  trapped tmp file "third.tmp" to rm
  -rw-rw-r-- 1 anadin ctgb 15 Jul  4  2017 third.tmp

final check first.tmp:
-rw-rw-r-- 1 anadin ctgb 15 Jul  4 15:54 first.tmp

final check second.tmp:
-rw-rw-r-- 1 anadin ctgb 16 Jul  4 15:54 second.tmp

final check third.tmp:
-rw-rw-r-- 1 anadin ctgb 15 Jul  4 15:54 third.tmp

I expected the file third.tmp to be deleted before the end of the script. The strange thing is, only the second.tmp file has been cancelled:

$ ls *.tmp
first.tmp  third.tmp

I expect the third file only to be removed after the function exits. I expect the two other files to be removed after completion of the script.

What is wrong here?

1

Since the third trap is created in a subshell it is also activated/run when that shell exits, attempting to remove the third file before it's been created. Therefore the third file exists after the script is done.

Every time you trap […] SIGNAL you overwrite the trap for that signal, so only the second trap survives in the top shell. Therefore the first file exists after the script is done.

An echo in the trap or possibly set -o xtrace would show you better what's going on. You can also run trap on its own to see which traps are in effect.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.