0

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 &
Dudi Boy
  • 4,551
  • 1
  • 15
  • 30
Mysterious Jack
  • 621
  • 6
  • 18
  • I believe the problem is after starting the background process the main script stops running and so does not trap any signals. You can verify this by checking the processes started for first_fun and second_fun. Both have PID 1 as their parent, meaning they're orphaned. I still dont know how to solve this but maybe this helps search better :) Update: Just after starting a process with & you can use $! to get its PID. But again not sure if this can help since your main script stops anyways. https://stackoverflow.com/questions/1908610/how-to-get-process-id-of-background-process – Devansh Sharma Feb 20 '22 at 07:59
  • I think Ctrl-Z generates `SIGSTOP`, not `SIGINT`. – Philippe Feb 20 '22 at 13:57

2 Answers2

0

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.

Dudi Boy
  • 4,551
  • 1
  • 15
  • 30
  • Even Double quotes do not work when pressing CTRL+Z. I think there is no way until some one else runs pskill from another terminal. – Mysterious Jack Feb 20 '22 at 08:22
  • CTRL-Z is a standard ssuspend signal. Keeps the process suspended in background until brought back to foreground with `fg` command. Better use CTRL-C to stop/kill process. – Dudi Boy Feb 20 '22 at 09:24
  • Are you sure about `-f $PWD` ? From man page : `When -f is set, the full command line is used` – Philippe Feb 20 '22 at 13:51
  • If your background programs are invoked with full/absolute path, it is possible to use $PWD to kill them with `pkill` – Dudi Boy Feb 20 '22 at 16:30
0

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
Darkman
  • 2,941
  • 2
  • 9
  • 14