I want to perform a command that takes about 1 minute to finish, in a bash script. However, sometimes this command hangs, so I want to use /usr/bin/timeout inside a loop until it works.
If I use timeout 300 mycommand myarg1
, it works, but if I use it inside bash in this loop below, it doesn't print anything (not even the typical output that my command prints) and it hangs!:
until timeout 300 mycommand myarg
do
echo "The command timed out, trying again..."
done
My version of bash:
$ bash --version
GNU bash, version 4.3.48(1)-release (x86_64-pc-linux-gnu)
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
My version of timeout:
$ timeout --version
timeout (GNU coreutils) 8.25
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
(Standard Ubuntu16.04)
How to Use the Bash Sleep Command. Sleep is a very versatile command with a very simple syntax. It is as easy as typing sleep N . This will pause your script for N seconds, with N being either a positive integer or a floating point number.
timeout is a command-line utility that runs a specified command and terminates it if it is still running after a given period of time. In other words, timeout allows you to run a command with a time limit.
The Bash has three types of looping constructs namely for, while, and until. The Until loop is used to iterate over a block of commands until the required condition is false. Syntax: until [ condition ]; do block-of-statements done.
The problem with
(mycommand args) & pid=$!
sleep 1000 && kill -INT $pid
is that it always takes 1000 seconds. Taking a more active (and CPU consuming) approach will shorten that time:
typeset -i i
i=0
command with arguments &
pid=$!
while ps $pid > /dev/null 2>/dev/null ; do
i=$i+1
if [ $i -gt 999 ] ; then
kill -9 $pid
fi
sleep 1
done
Or, if your system is not too busy or the interval is short:
command with arguments &
pid=$!
echo "kill -9 $pid" | at "now + 15 minutes"
wait
But timeout
will also work, of course.
The reason why
until timeout 300 mycommand myarg
do
echo "The command timed out, trying again..."
done
hangs is that bash will try to evaluate the condition for your until
, which may take upto 300 seconds. If timeout 300 mycommand myarg
returns a success, the until is never executed. Try for example:
if timeout 30 mycommand myarg ; then
echo "The timeout of mycommand succeeded"
else
echo "It failed! What a pitty"
fi
This works like a charm.
When command finish:
sh timeoutLoop.sh 4
OUTPUT:
Seconds start now...
3 seconds passed...
When command not finish:
sh timeoutLoop.sh 2
OUTPUT:
Seconds start now...
The command timed out, trying again...
Seconds start now...
The command timed out, trying again...
Seconds start now...
The command timed out, trying again...
Seconds start now...
The command timed out, trying again...
...
Your mycommand = waitSeconds.sh
#!/bin/bash -
echo "Seconds start now..."
sleep $1
echo "$1 seconds passed..."
And the loop bash timeoutLoop.sh
#!/bin/bash -
until timeout $1 waitSeconds.sh 3
do
echo 'The command timed out, trying again...'
done
Try this, and don't forget the header of the script.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With