Recovery after bash traps

I have a bash script with some file manipulations, and I would like to process the loop to the end of the block after pressing CTRL + C. I gave an example:

#!/bin/bash # Register signal handler ABORT=0; trap ABORT=1 SIGINT; # Create temp dir TEMPDIR=$(mktemp -d -t $0); # Helper functions function do_other_stuff { true; } # Process files for ((COUNTER = 0; COUNTER < 3 && ABORT == 0; COUNTER++)); do FILE=/some/directory/$COUNTER.txt; BASE=$(basename $FILE); cp $FILE $TEMPDIR; > $FILE; do_other_stuff; cp $TEMPDIR/$BASE $FILE; rm $TEMPDIR/$BASE; done; rm -rf $TEMPDIR; 

This works very well, but I noticed that sometimes BASE in the statement

 BASE=$(basename $FILE); 

not set if a trap occurs during the basename command. This leads to errors in cp and the following commands.

Did I miss something? How does bash recover from traps? Is there any other solution with the same effect?

+4
source share
1 answer

Instead

 BASE=$(basename $FILE); 

Instead of this:

 BASE=${FILE##*/} 

It’s also nice to place your work functions in the background from the interface that handles SIGINT. Just don't ask for input in it. Also, always specify your variables correctly.

 #!/bin/bash # Register signal handler ABORT=0; trap ABORT=1 SIGINT; # Create temp dir TEMPDIR=$(mktemp -d -t $0); # Helper functions function do_other_stuff { true; } # Process files for ((COUNTER = 0; COUNTER < 3 && ABORT == 0; COUNTER++)); do ( FILE=/some/directory/$COUNTER.txt BASE=${FILE##*/} cp "$FILE" "$TEMPDIR" > "$FILE" do_other_stuff cp "$TEMPDIR/$BASE" "$FILE" rm "$TEMPDIR/$BASE" ) & CPID=$! # Handle SIGINT but don't end the loop until subprocess finishes its work. while kill -s 0 CPID &>/dev/null; do ## Checks if subprocess is still there. # Wait if yes. wait "$CPID" done done rm -rf "$TEMPDIR" 

This will quickly abort the operation:

 # Process files for ((COUNTER = 0; COUNTER < 3 && ABORT == 0; COUNTER++)); do ( FILE=/some/directory/$COUNTER.txt BASE=${FILE##*/} cp "$FILE" "$TEMPDIR" > "$FILE" do_other_stuff cp "$TEMPDIR/$BASE" "$FILE" rm "$TEMPDIR/$BASE" ) & CPID=$! while wait "$CPID" if [[ ABORT -eq 1 ]]; then kill -s ABRT "$CPID" &>/dev/null break fi kill -s 0 "$CPID" &>/dev/null do continue done done rm -rf "$TEMPDIR" 
+1
source

Source: https://habr.com/ru/post/1501157/


All Articles