6
votes

I want an infinite loop to keep on running, and only temporarily be interrupted by a kill signal. I've tried SIGINT, SIGUSR1, SIGUSR2. All of them seem to halt the loop. I even tried SIGINFO, but that wasn't supported by Linux.

#!/bin/bash
echo $$ > /tmp/pid  # Save the pid

function do_something {
    echo "I am doing stuff" #let's do this now, and go back to doing the thing that is to be done over and over again.
#exit
}


while :
do
    echo "This should be done over and over again, but always wait for someething else to be done in between"

    trap do_something SIGINT
    while `true`
    do
            sleep 1 #so we're waiting for that other thing.
    done

done

My code runs the function once, after getting a INT signal from another script, but then never again. It halts.

EDIT: Although I accidentally put en exit at the end of the function, here on Stack Overflow, I didn't in the actual code I used. Either way, it made no difference. The solution is SIGTERM as described by Tiago.

3

3 Answers

6
votes

I believe you're looking for SIGTERM:

Example:

#! /bin/bash

trap -- '' SIGINT SIGTERM
while true; do
    date +%F_%T
    sleep 1
done

Running this example cTRL+C won't kill it nor kill <pid> you can however kill it with kill -9 <pid>.

If you don't want CTRL+Z to interrupt use: trap -- '' SIGINT SIGTERM SIGTSTP

1
votes

trap the signal, then either react to it appropriately, in the function associate with the trap, or ignore it by for example associate : as command to get executed when the signal occurs.

to trap signals, bash knows the trap command

Reset trap to former action by executing trap with signal name only.

Therefore you want to (i think that's what you say you want with "only temporarily be interrupted by a kill signal"):

  • trap the signal at the begin of your script: trap signal custom_action
  • just before you want the signal to allow interrupting your script, execute: trap signal
  • At the end of that phase, trap again by: signal custom_action

to specify signals, you can also use their respective signal numbers. A list of signal names is printed with the command:

trap -l 

the default signal sent by kill is SIGTERM (15), unless you specify a different signal after the kill command

don't exit in your do_something function. Simply let the function return to the section in your code where it was interrupted when the signal occured.

The mentioned ":" command has another potential use in your script, if you feel thusly inclined:

while :
do
  sleep 1
done

can be an alternative to "while true" - no backticks needed for that, btw.

0
votes

You just want to ignore the exit status.
If you want your script to keep running and not exit, without worrying about handling traps.

(my_command) || true

The parentheses execute that command in a subshell. The true is for compatibility with set -e, if you use it. It simply overrides the status to always report a success.

See the source.

I found this question to be helpful: How to run a command before a Bash script exits?