I´ve asked Bash trap - exit only at the end of loop and the submitted solution works but while pressing CTRL-C the running command in the script (mp3convert with lame) will be interrupt and than the complete for loop will running to the end. Let me show you the simple script:
#!/bin/bash
mp3convert () { lame -V0 file.wav file.mp3 }
PreTrap() { QUIT=1 }
CleanUp() {
if [ ! -z $QUIT ]; then
rm -f $TMPFILE1
rm -f $TMPFILE2
echo "... done!" && exit
fi }
trap PreTrap SIGINT SIGTERM SIGTSTP
trap CleanUp EXIT
case $1 in
write)
while [ -n "$line" ]
do
mp3convert
[SOMEMOREMAGIC]
CleanUp
done
;;
QUIT=1
If I press CTRL-C while function mp3convert is running the lame command will be interrupt and then [SOMEMOREMAGIC] will execute before CleanUp is running. I don´t understand why the lame command will be interrupt and how I could avoid them.
One way of doing this would be to simply disable the interrupt until your program is done. Some pseudo code follows:
Another idea would be to run your bash script in the background (if possible).
or even,
When you hit Ctrl-C in a terminal, SIGINT gets sent to all processes in the foreground process group of that terminal, as described in this Stack Exchange "Unix & Linux" answer: How Ctrl C works. (The other answers in that thread are well worth reading, too). And that's why your mp3convert function gets interrupted even though you have set a SIGINT trap.
But you can get around that by running the mp3convert function in the background, as mattias mentioned. Here's a variation of your script that demonstrates the technique.
When you hit Ctrl-C while
myfunc
is in the middle of a run,PreTrap
prints its message and sets the QUIT flag, butmyfunc
continues running andCleanUp
doesn't commence until the currentmyfunc
run has finished.Note that my version of
CleanUp
resets the QUIT flag. This preventsCleanUp
from running twice.This version removes the
CleanUp
call from the main loop and puts it inside thePreTrap
function. It useswait
with no ID argument inPreTrap
, which means we don't need to bother saving the PID of each child process. This should be ok since if we're in the trap we do want to wait for all child processes to complete before proceeding.We don't really need to do
myfunc "$i" & wait $!
in this script, it could be simplified even further tomyfunc "$i" & wait
. But generally it's better to wait for a specific PID just in case there's some other process running in the background that we don't want to wait for.Note that pressing Ctrl-C while
CleanUp
itself is running will interrupt the current foreground process (probablysleep
in this demo).Try to simplify the discussion above, I wrap up an easier understandable version of show-case script below. This script also HANDLES the "double control-C problem": (Double control-C problem: If you hit control C twice, or three times, depending on how many
wait $PID
you used, those clean up can not be done properly.)The
kill -0
trick can be found in a comment of this link