Home > other >  How to stop all background processes(running functions) by using Trap?
How to stop all background processes(running functions) by using Trap?

Time:02-21

I have two long running functions which needs to be executed asynchronously. For simplicity, assume one function sends Mail to client every 10 seconds & other logs text file every two seconds.

I cannot use cron jobs to do this. Everything has to be in one script. Thus I have used infinite loops and sleep with & achieve asynchronous behavior.

Used to trap 'pkill -P $$' SIGINT SIGTERM to end all child processes(to end program) when user hits CTRL Z (SIGINT) but this doesn't work. It again starts script execution even after pressing CTRL Z.

How can I give user the ability to end program with keyboard clicks from same terminal?

Note: Those two functions are never ending until user manually stops the program.

echo "Press: CTRL Z to Close program"

trap 'pkill -P $$' SIGINT SIGTERM

first_fun()
{
    while :; do
        echo "send Mail every 10 seconds"
        sleep 10
    done
}

second_fun()
{
    while :; do
        echo "log text file every 2 seconds"
        sleep 2
    done
}

first_fun &

second_fun &

CodePudding user response:

Suggesting to use " to let the shell interpret $$. Like this:

 trap "pkill -9 -P $$" 

Also suggesting to kill all process running from current directory, because process ancestory is not always working (e.g using nohup command):

 trap "pkill -9 -f $PWD" 

Also suggesting to kill/stop a process with CTRL-C (the standard) and avoid CTRL-Z used for suspending processes.

CodePudding user response:

When problem with your script was that the script exists after runs those two functions. So "$$" is no longer refers to the script. An easy fix is to put a wait at the end of the script. Also change to this might help

trap "pkill -P $$" INT TERM

But, what I would do is to kill those functions rather than killing the script:

echo "Press: CTRL Z to Close program"

first_fun()
{
    while :; do
        echo "send Mail every 10 seconds"
        sleep 10
    done
}

second_fun()
{
    while :; do
        echo "log text file every 2 seconds"
        sleep 2
    done
}

_INTERRUPTED
_PID1
_PID2

interrupt()
{
    # Do this once.
    if [[ -z "$_INTERRUPTED" ]]; then
        _INTERRUPTED='true'
        kill -KILL "$_PID1"
        kill -KILL "$_PID2"
    fi
}

trap interrupt INT TERM EXIT
first_fun &
_PID1="$!"
second_fun &
_PID2="$!"
wait
  • Related