David Bailey
David Bailey

Reputation: 1091

Prevent CTRL+C being sent to process called from a Bash script

Here is a simplified version of some code I am working on:

#!/bin/bash

term() {
  echo ctrl c pressed!
  # perform cleanup - don't exit immediately
}
trap term SIGINT

sleep 100 &
wait $!

As you can see, I would like to trap CTRL+C / SIGINT and handle these with a custom function to perform some cleanup operation, rather than exiting immediately.

However, upon pressing CTRL+C, what actually seems to happen is that, while I see ctrl c pressed! is echoed as expected, the wait command is also killed which I would not like to happen (part of my cleanup operation kills sleep a bit later but first does some other things). Is there a way I can prevent this, i.e. stop CTRL+C input being sent to the wait command?

Upvotes: 2

Views: 2316

Answers (2)

David Bailey
David Bailey

Reputation: 1091

I ended up using a modified version of what @thatotherguy suggested:

#!/bin/bash

term() {
  echo ctrl c pressed!
  # perform cleanup - don't exit immediately
}
trap term SIGINT

sleep 100 &
pid=$!

while ps -p $pid > /dev/null; do
  wait $pid
done

This checks if the process is still running and, if so, runs wait again.

Upvotes: 2

that other guy
that other guy

Reputation: 123490

You can prevent a process called from a Bash script from receiving sigint by first ignoring the signal with trap:

#!/bin/bash
# Cannot be interrupted
( trap '' INT; exec sleep 10; )

However, only a parent process can wait for its child, so wait is a shell builtin and not a new process. This therefore doesn't apply.

Instead, just restart the wait after it gets interrupted:

#!/bin/bash
n=0
term() {
  echo "ctrl c pressed!"
  n=$((n+1))
}
trap term INT


sleep 100 &

while
  wait "$!"
  [ "$?" -eq 130 ]   # Sigint results in exit code 128+2
do
  if [ "$n" -ge 3 ]
  then
    echo "Jeez, fine"
    exit 1
  fi
done

Upvotes: 4

Related Questions