11

I tried to have an interactive program in a bash script :

my_program

And I wish to be able to close it with 'Ctrl + c'. But when I do it my script is closing as well.

I know about.

trap '' 2
my_program
trap 2

But in this case, I just can't close my_program with Ctrl + c.

Do you have any idea how to allow Ctrl + c on a program, but not closing the script running it ?

EDIT : add example

#!/bin/bash
my_program
my_program2

If i use Ctrl + c to close my_program, my_program2 is never executed because the whole script is exited.

13

You should use trap true 2 or trap : 2 instead of trap '' 2. That's what "help trap" in a bash shell says about it:

If ARG is the null string each SIGNAL_SPEC is ignored by the shell and by the commands it invokes.

Example:

$ cat /tmp/test
#! /bin/sh
trap : INT
cat
echo first cat killed
cat
echo second cat killed
echo done
$ /tmp/test
   <press control-C>
^Cfirst cat killed
   <press control-C>
^Csecond cat killed
done
  • 2
    How about killing tails instead of killing cats next time? – kubanczyk Sep 11 '18 at 7:13
12

You can reset a trap to its default by giving the trap command - as its action argument. If you do this in a subshell, it won't affect the trap in the parent shell. In your script, you can do this for each command that you need to be interruptible with Ctrl-C:

#!/bin/bash
# make the shell (and its children) ignore SIGINT
trap '' INT
.
.
.
# but this child won't ignore SIGINT
(trap - INT; my_program)
# the rest of the script is still ignoring SIGINT
.
.
.
  • 1
    While the accepted answer is probably better and more canonical for shell, this is a great answer in itself in that it introduces the general principle (not shell-specific) for how to do this sort of signal masking/ignoring safely. – R.. Sep 10 '18 at 17:11
  • I guess you can exec my_program in the subshell, to be slightly more efficient. – Toby Speight Sep 10 '18 at 17:15
  • @R.. that's absolutely not shell specific -- if you set a signal to SIG_IGN (that's what trap with an empty string is doing), that state will be inherited through exec(), except for SIGCHLD. That's POSIX mandated behavior. See also the answer to stackoverflow.com/questions/32708086/… – mosvy Sep 10 '18 at 17:26
  • @mosvy: I don't see what part of my comment you're disagreeing with. My whole point was that "mask/ignore before fork, unmask/unignore in the child before exec" is a general principle that's useful to know outside the context of just shell programming. – R.. Sep 10 '18 at 17:30
  • 1
    This is a very useful answer. As an experienced Linux user, I can say I've never heard of this before. It has quite a lot of uses... you got my upvote and my bookmark. – Dev Sep 11 '18 at 4:37
-1


When you use Crtl+C, you interrupt the program ("kill" it).
What you are probably looking for is to suspend your program ("pause" it). For this, you can use Crtl+Z.
Once your program is paused, you can see it using jobs. For example:
[1]+ Stopped ./foobar
Here I only have one job, job #1, but there can be more than one - each job has its own number.
You can control you suspended process using a number of commands, for example bg, fg and kill.
bg %1 will restart job #1 in the background
fg %1 will restart job #1 in the foreground
kill %1 will kill job #1
Note that you can use bg and fg with no arguments if you only have one active job.

  • Thank you but no, I wish to do Ctrl + c. – bob dylan Sep 10 '18 at 12:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.