1

In a shell script, I do the following:

#!/bin/sh

while true; do <some application>; sleep 1; done &

... rest of the scrip ...

This guarantees that the application is always running, as this is needed for the rest of the script. The script is resilient however, so if the application does not seem to be run and answer incorrectly, it will retry later on.

When the main script dies, for example due to a SIGTERM or SIGINT, I want that while loop to stop as well. There is no need to keep the applicaiton running after the main script dies.

What is the common approach to do this in shell scripting? Note that I want two things:

  1. prevent re-execution of the application
  2. stop the current ongoing application instance as soon as possible

I am not sure how to do all this in shell scripting. I could trap INT and TERM, but I'm not sure how to inject logic into the while loop and also how to stop the application as well.

Note that I am currently working in plain sh, but I can move on to bash if needed.

2
  • Re: jim's answer, you might clarify whether you're specifically backgrounding the application in the while loop or not, as the only evidence right now is the backgrounded while loop.
    – Jeff Schaller
    Jul 12, 2019 at 17:39
  • @JeffSchaller Could you please clarify? I'm not sure what you are saying. As far as I understand, the whole while true; do ...; done is running in the background, isn't it?
    – Pritzl
    Jul 12, 2019 at 19:55

2 Answers 2

1

What you want in your script is not an infinite loop, but a lock file.

Then call the script that does the work within the wrapper script.

#!/bin/sh

if [ -f /tmp/.lock.my-mgr ]
then
        echo "Program in use ... exiting ..."
        exit 10
fi

/bin/touch /tmp/.lock.my-mgr

/usr/local/bin/myscript.sh

/bin/rm /tmp/.lock.my-mgr

If you want this task to be done as a batch every few minutes, then use cron to schedule that.

Edit:

The PID of the script running with the loop could be put in a file with something like

echo $! > /var/tmp/script1.pid

(in one script).

To test if it is up from a second script, use ps command, something like

ps -p `cat /var/tmp/script1.pid`

and then test the status of that with $? variable which should be 0 if ps found that pid, or 1 if it did not. That's the basic logic but it could be written with better tests like in case the pid file didn't exist.

5
  • Thank you. I can see the point of introducing a lock, as a meaning to have a shared variable between the main script and loop, so to say. But how do I kill the ongoing application? It could continue running for years, so to speak.
    – Pritzl
    Jul 12, 2019 at 17:21
  • Also, I would like to continue the inlining of that while loop, if that is possible. I would rather not end up with a bunch of .sh files. Ideally, there is just one .sh file, for the main script.
    – Pritzl
    Jul 12, 2019 at 17:26
  • The above is a solution for preventing re-execution of the script. You might find it easier to create a solution involving two scripts, and have some sort of test within one that it can find the other is running, whether that is a lock file or PID stored in a file. That is a common technique used in old style init.d scripts.
    – labradort
    Jul 12, 2019 at 18:02
  • I see how this prevents re-execution, which is nice. But I don't see how to kill the current instance of the <some application> as originally started in while true; do <some application>; sleep 1; done &. How do you do that? If you combine solution with killing the current instance, I think we are set.
    – Pritzl
    Jul 12, 2019 at 18:06
  • Editing the answer to include more ideas...
    – labradort
    Jul 12, 2019 at 19:19
0
while true; do <some application>; sleep 1; done &
myloop=$!   # get the pid of the child
#  kill $myloop 
#   where/when you think you need to stop the child process

The & creates a child process in the background. There are other commands that deal with job like fg that you may want to consider.

2
  • But what does $! refer to? The PID of last child, I know, but is that of the process container representing the while loop, or of the process of <some application>? And what if the application has been restarted a few times? Will it be updated?
    – Pritzl
    Jul 12, 2019 at 16:44
  • $! is the pid of the last backgrounded process, so it'd be of the while loop, here.
    – Jeff Schaller
    Jul 14, 2019 at 12:56

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .