Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Terminate a process started by a bash script with CTRL-C

Tags:

linux

bash

I'm having an issue with terminating the execution of a process inside a bash script.

Basically my script does the following actions:

  1. Issue some starting commands
  2. Start a program who waits for CTRL+C to stop
  3. Do some post-processing on data retreived by the program

My problem is that when I hit CTRL+C the whole script terminates, not just the "inner" program.

I've seen around some scripts that do this, this is why I think it's possible.

Thanks in advance!

like image 927
magicleon94 Avatar asked May 10 '16 16:05

magicleon94


People also ask

Does Ctrl C Terminate process?

ctrl c is used to kill a process. It terminates your program. ctrl z is used to pause the process. It will not terminate your program, it will keep your program in background.

What does Ctrl C does in bash?

Bash will run commands in separate process groups and Ctrl + c will get to the group being the foreground process group at the moment.

How do I stop a Bash script execution?

If you are executing a Bash script in your terminal and need to stop it before it exits on its own, you can use the Ctrl + C combination on your keyboard.

How do you end a process in bash?

To interrupt it, you can try pressing ctrl c to send a SIGINT. If it doesn't stop it, you may try to kill it using kill -9 <pid> , which sends a SIGKILL. The latter can't be ignored/intercepted by the process itself (the one being killed). To move the active process to background, you can press ctrl z .


1 Answers

You can set up a signal handler using trap:

trap 'myFunction arg1 arg2 ...' SIGINT;

I suggest keeping your script abortable overall, which you can do by using a simple boolean:

#!/bin/bash

# define signal handler and its variable
allowAbort=true;
myInterruptHandler()
{
    if $allowAbort; then
        exit 1;
    fi;
}

# register signal handler
trap myInterruptHandler SIGINT;

# some commands...

# before calling the inner program,
# disable the abortability of the script
allowAbort=false;
# now call your program
./my-inner-program
# and now make the script abortable again
allowAbort=true;

# some more commands...

In order to reduce the likelihood of messing up with allowAbort, or just to keep it a bit cleaner, you can define a wrapper function to do the job for you:

#!/bin/bash

# define signal handler and its variable
allowAbort=true;
myInterruptHandler()
{
    if $allowAbort; then
        exit 1;
    fi;
}

# register signal handler
trap myInterruptHandler SIGINT;

# wrapper
wrapInterruptable()
{
    # disable the abortability of the script
    allowAbort=false;
    # run the passed arguments 1:1
    "$@";
    # save the returned value
    local ret=$?;
    # make the script abortable again
    allowAbort=true;
    # and return
    return "$ret";
}

# call your program
wrapInterruptable ./my-inner-program
like image 169
Siguza Avatar answered Oct 02 '22 21:10

Siguza