Home > Blockchain >  trapping CTRL C in shell into pipe
trapping CTRL C in shell into pipe

Time:09-20

I have a shell script (example.sh) in which I am creating and allocating (mounting) space in the /media directory and I'm copying some files there for faster processing.

ram_disk=/media/ram_disk
sudo mount -t tmpfs -o size=100000000 tmpfs "$ram_disk"
sudo cp "$some_random_file" "$ram_disk"

At the end of this shell script, I unmount and delete $ram_disk as follows-

sudo umount "$ram_disk"
cd /media
sudo rm -r "$ram_disk"

So that CTRL C interruptions doesn't create problems, I've added a trap handler at the start (first lines) of the shell script

ctrlc_count=0

    function no_sigint {
    
        let ctrlc_count  
        if [[ $ctrlc_count == 1 ]]; then
            echo "Aborting process"
            if [ -d "$ram_disk" ]; then
            sudo umount "$ram_disk"
            cd /media
            sudo rm -r "$ram_disk"
            else
            :
            fi
        fi
    
    }
    
    trap no_sigint SIGINT

And if no SIGINT is supplied, variable ctrlc_count remains 0 and ram_disk is removed normally at the end of the shell script (last lines)-

if [[ $ctrlc_count == 0 ]]; then
      sudo umount "$ram_disk"
      cd /media
      sudo rm -r "$ram_disk"
fi

This has been working fine so far. However, if I pipe the shell script with another bash command and supply SIGINT, the trap handler does not work -

bash example.sh | head -10
bash example.sh | tail -10

Using CTRL C in the above scenario does not remove $ram_disk.

Any suggestions on how can I improve my code to take piping commands into consideration? Thank you.

CodePudding user response:

Trap EXIT instead of SIGINT.

SIGINT refers to an interrupt signal, generated by Ctrl-C by default. That's not the only condition that can end a script.

EXIT commands will run when the script exits regardless of the reason - unless it's an uncatchable signal such as SIGKILL.

CodePudding user response:

Trapping EXIT is a good solution, but it doesn't explain the behavior you're seeing.

When you use ctrl-C to send SIGINT to the foreground process group, the tail/head gets terminated. The SIGINT trap in the bash script is executed, but in bash echo is a builtin so the echo "Aborting process" generates a SIGPIPE to the script which is uncaught and the script immediately terminates. Writing error messages/diagnostics to stderr isn't just a good idea, it saves your from this bug. The "correct" solution is to trap EXIT, but a (potentially) easier approach is to use echo 'Aborting process' >&2.

  • Related