This seems to work:
trap "pressed_ctrl_c=1" INT
(trap "" INT; foo)&
wait || wait
if [ "$pressed_ctrl_c" ]
pressed_ctrl_c to null.
This is probably not necessary in a script.
trap command signum tells the shell
to set up to catch signal number
command when it catches one.
“INT” is short for “SIGINT” which is short for “interrupt signal”,
which is the technical term for the signal generated
by Ctrl+C, so,
when you type Ctrl+C,
the shell sets
pressed_ctrl_c to 1.
(SIGINT has a numeric value of 2,
so you can say
trap "pressed_ctrl_c=1" 2 if you want to economize on typing.)
- Inside the loop, we have a command line in parentheses.
This creates a sub-shell.
- We use the
trap command again.
command is a null string;
this tells the shell to ignore signal number
Since this is inside the parentheses, it affects only the subshell.
Since it was run from the subshell,
foo will ignore Ctrl+C,
i.e., it will keep on running even if you type it.
- Put the subshell in the background ….
- … and wait for it to complete.
- If the
wait command succeeds, go on to the
If it fails, execute another one.
(I’ll get back to this.)
$pressed_ctrl_c is set, break out of the loop.
Optionally uncomment the
if Ctrl+C appears on your terminal as
and you want to move to the next line.
We run a command in the background, and then immediately
wait for it.
This is very similar to running the command in the foreground
(at least, when done in a script).
wait command will terminate successfully when the subshell terminates;
i.e., when the
foo command terminates.
wait command will terminate successfully
foo returns an error.)
When the first
wait command terminates successfully,
we skip the second one and go to the
The shell that’s running the loop is catching interrupts,
but the subshell, and thus the
foo process, are ignoring them.
So, when you type Ctrl+C,
the shell sets
pressed_ctrl_c to 1 and aborts the (first)
Since the first
wait command failed, we go on to the second one.
foo subshell is still running,
wait still has something to do
(i.e., it will wait for the
foo to finish.)
Finally, if the variable has been set to indicate
that a Ctrl+C has been pressed while
foo was running,
break output the loop.
If you press Ctrl+C twice,
the second one will interrupt and abort the second
This will cause your script to terminate and return you to your shell prompt,
foo running in the background.
You can mitigate this by saying
wait || wait || wait || wait;
extending it as far as you want.
You would need to type Ctrl+C once for each
to terminate the script prematurely.
A problem with this is that processes that are put into the background
by a script have their standard input set to
foo reads from the keyboard, the above will need revision.