bashshellscopebash-trap

Bash signal capture not detecting variables changed after declaration of 'trap' block


I have a bunch of generic cleanup code that needs to be done whenever a certain bash script exits, whether it exited normally or was interrupted. I figured I'd use the trap "..." EXIT pseudosignal to achieve this.

In addition to the generic cleanup stuff, there's also one piece of specific cleanup that should only be done if the script completes normally. I thought I could trigger this by having the 'trap' block test a variable, like so:

#!/bin/bash
done=false;
trap "{        
           #generic cleanup code goes here.
           if $done
           then
               #cleanup to be done only on completion goes here.
               echo Test;
           fi
       }" EXIT
#main script goes here
done=true;

However, this doesn't work. Running the following code will never echo "Test". Adding an explicit exit call after done=true; doesn't change anything. What am I missing?

Cheers!


Solution

  • The trap is being interpolated, and is using the value of $done at the time the trap is being defined rather than when it is executed. You can use single quotes around the trap definition, or define a function. Defining a function is probably cleaner:

    #!/bin/sh
    done=false
    cleanup() { if test "$done" = true; then echo Test; fi; }
    trap cleanup EXIT
    done=true
    

    This works because the expansion of variables in the function is deferred until the function is called, rather than when the function is defined.