0

Scenario:
I have a shell script running on embedded linux. The script starts an application which needs the state of a variable to be on.

Code:
So I do it like this

#!/bin/sh

start_my_app=false

wait_for_something=true
while $wait_for_something; do

    wait_for_something=$(cat /some/path/file)

    if [ "$wait_for_something" = "false" ]
    then
        echo Waiting...
    elif [ "$wait_for_something" = "true" ]
    then
        echo The wait has ended
        wait_for_something=false
        start_my_app=true
    else

    fi

done

if [ "$start_my_app" = "true" ]
then
    /usr/bin/MyApp
fi

#End of the script

/some/path/file has a value false and turns to true in a few seconds by another script in different component. And then as the logic goes wait_for_something in my script becomes true and /usr/bin/MyApp is started.

The problem and hence the question:
But I want to do it in a better way.
I dont want to wait infinitely in a while loop expecting the content value in /some/path/file to be set true after some time.

I want to wait for the content value in /some/path/file to be set true for only 5 seconds. If /some/path/file does not contain true in 5 seconds, I want to get out setting start_my_app to false.

How can I achieve this functionality in a shell script on linux?

PS:
My whole script is run in the background by another script

jww
  • 97,681
  • 90
  • 411
  • 885
TheWaterProgrammer
  • 7,055
  • 12
  • 70
  • 159
  • 1
    You sleep for 2 seconds between each check. Why don't you just stop iterating after 3 times, for a total of ~6 seconds? – that other guy Oct 16 '18 at 16:53
  • I removed the sleep but I think I can wait on seconds elapsed to count till 6 I guess – TheWaterProgrammer Oct 16 '18 at 17:01
  • 1
    You should probably have at least a small sleep. No point using 100% CPU for five seconds. The alternative is using a named pipe instead of a regular file, which you can just wait on with a timeout. – that other guy Oct 16 '18 at 17:06
  • ah. ok. Thats a good point I should remove the sleep then. Ok. Another thing I found [in this discussion](https://stackoverflow.com/questions/5152858/how-do-i-measure-duration-in-seconds-in-a-shell-script), that there is a way to check how much time I waited. – TheWaterProgrammer Oct 16 '18 at 17:10
  • @thatotherguy I anyways got the answer. I can close the question or happy to accept an answer you post based on the counters technique with sleep 2 – TheWaterProgrammer Oct 16 '18 at 17:18
  • 2
    Possible duplicate of [Time condition loop in shell](https://stackoverflow.com/q/11176284/608639) and [Timeouting a while loop in Linux shell script](https://stackoverflow.com/q/27555727/608639). Also see [How to kill a child process after a given timeout in Bash?](https://stackoverflow.com/q/5161193/608639) – jww Oct 17 '18 at 03:32

1 Answers1

3

Use the SECONDS variable as a timer.

SECONDS=0
while (( SECONDS < 5 )) && IFS= read -r value < /some/path/file; do
  if [[ $value = true ]]; then
    exec /usr/bin/MyApp
  fi
done

If you never read true from the file, your script will exit after 5 seconds. Otherwise, the script replaces the current shell with MyApp, effectively exiting the while loop.

chepner
  • 497,756
  • 71
  • 530
  • 681
  • Good news is that `SECONDS` can be used in a POSIX shell as well, not only in `bash`. – ob-ivan Aug 19 '21 at 09:08
  • 1
    @ob-ivan `SECONDS` is not defined by POSIX. It's an ordinary variable in `dash`, for example. – chepner Aug 19 '21 at 12:06
  • My bad, I didn't test it properly. My loop was exiting before reaching the timeout, so I simply assumed it worked. Incrementing an ordinary variable is a way to go then. – ob-ivan Aug 19 '21 at 13:55