7

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.

Paolo
  • 2,161
  • 5
  • 25
  • 32

3 Answers3

7

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

Tiago Lopo
  • 7,619
  • 1
  • 30
  • 51
  • you missed a problem in his do_something function - i also almost did: the/a problem of script terminating is that there is an exit at the end. Therefore, even with the right signal, the problem still exists. Seems those uprating your answer also missed that. Witness "My code runs the function once, after getting a INT signal from another script, but then never again." – Deleted User Jul 20 '14 at 10:05
  • @Bushmills You're right, I didn't see the exit, but I gave OP an example showing how not to be interrupted. I think that's the reason of upvotes. – Tiago Lopo Jul 20 '14 at 10:15
  • @Tiago, any idea on how to make it return to the infinite loop, even after every time do_something is run? – Paolo Jul 20 '14 at 11:16
  • 1
    To be immune trap `SIGQUIT SIGHUP SIGINT SIGTERM SIGUSR1 SIGUSR2` Also think about `SIGPIPE` – kubanczyk Apr 07 '20 at 14:42
  • What does the `--` do in `trap -- '' SIGINT SIGTERM`? – 2072 Jul 05 '20 at 13:14
1

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.

Deleted User
  • 2,551
  • 1
  • 11
  • 18
  • Thank you. But in my example, it traps the signal, runs do_something, but then just stops. It never returns to the infinite loop bellow. What am I missing? – Paolo Jul 20 '14 at 10:58
  • it'S not that you're missing something, it is that there is too much: I wrote in my answer "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 "exit" exits your script – Deleted User Jul 20 '14 at 11:08
  • But how do I make it return to the code where it was interrupted when the signal occured? I don't have an explicit exit, but perhaps that implicitly done anyway, at the end of the do_something? How do I prevent it from doing that then? Thanks. – Paolo Jul 20 '14 at 11:18
  • simply remove the exit. And yes, you do have an explicit exit. it is written in the code you posted. I don't know - nobody seems to see that exit, am I hallucinating? – Deleted User Jul 20 '14 at 12:15
  • You're not hallucinating, +1 for having spotted it. – Tiago Lopo Jul 20 '14 at 12:28
  • 1
    @Bushmills Indeed there is an exit, I accidentally put it there. Sorry about that. But removing it doesn't help. – Paolo Jul 21 '14 at 21:28
0

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?

kubanczyk
  • 5,184
  • 1
  • 41
  • 52
nelaaro
  • 3,006
  • 5
  • 38
  • 56