0

On stackoverflow there are many solutions - how to close script by timeout or close script if there is an error. But how to have both approaches together? If during execution of the script there is an error - close script. If timeout is out - close script.

I have following code:

#!/usr/bin/env bash
set -e
finish_time=$1
echo "finish_time=" ${finish_time}
(./execute_something.sh) & pid=$!
sleep ${finish_time}
kill $pid

But if there is an error while execution - script still waits, when timeout would be out.

Artur
  • 661
  • 1
  • 6
  • 23
  • So `wait` on child, with a timeout. And if you waited for shorter amount of time then `finish_time` and the exit status of child is zero, then wait up until `finish_time`. If child status is nonzero, then exit with error. If you `wait`ed for too long and it timeouted, then do something else. – KamilCuk May 08 '20 at 14:40
  • If you're on modern Linux (with GNU coreutils), you'll have a `timeout` command that does all this for you. Run `timeout "$finish_time" ./execute_something.sh` and there you are. – Charles Duffy May 08 '20 at 14:58

1 Answers1

1

First, I won't use set -e.

You'll explicitly wait on the job you want; the exit status of wait will be the exit status of the job itself.

echo "finish_time = $1"

./execute_something.sh & pid=$!
sleep "$1" & sleep_pid=$!

wait -n  # Waits for either the sleep or the script to finish
rv=$?

if kill -0 $pid; then
    # Script still running, kill it
    # and exit 
    kill -s ALRM $pid
    wait $pid  # exit status will indicte it was killed by SIGALRM
    exit
else
    # Script exited before sleep
    kill $sleep_pid
    exit $rv
fi

There is a slight race condition here; it goes as follows:

  1. wait -n returns after sleep exits, indicating the script will exit on its own
  2. The script exits before we can check if it is still running
  3. As a result, we assume it actually exited before sleep.

But that just means we'll create a script that ran slightly over the threshold as finishing on time. That's probably not a distinction you care about.

Ideally, wait would set some shell parameter that indicates which process caused it to return.

chepner
  • 497,756
  • 71
  • 530
  • 681