Timeouting a While Loop in Linux Shell Script

Timeouting a while loop in Linux shell script

I think that the solution to your problem is to execute another shell instance and pass proper commands to it.
According to bash manual:

-c        If the -c option is present, then commands are read from the first non-option argument command_string.

Thus my solution would be something like that:

timeout 5 bash -c -- 'while true; do printf ".";done'

-- assures that the following arguments will be treated as non-option. And '' helps with passing " without unnecessary escaping

Pass while loop to timeout

The argument to timeout is a command. It is not a shell expression. That is, it is the filename of a utility followed by the arguments to that utility. (You can use redirections, but the redirections are applied to the timeout command; they are not interpreted by timeout. Since timeout executes the specified command in the same execution environment, the redirections will be inherited by the command.)

As you say, you can use the bash command to run any bash expression, but quoting is awkward. Quoting can be simplified using here-docs:

timeout 60 bash <<"EOF"
while read id; do
find . -name $id -exec echo '{}' \;
find . -name ${id}-other -exec echo '{}' \;
done < <(grep foo foo.txt | awk '{print $1}')
EOF

Stop a loop process in shell scripting after some time

bash provides a special variable SECONDS that can be used as a rough timer.

SECONDS=0
while (( SECONDS < 60)); do
x=$(/opt/oc get pods --selector app=${bamboo.shortPlanName} -o jsonpath='{range .items[]}{.status.phase}{"\n"}{end}')
if [[ $x == Running ]]; then
break
fi
sleep 5
done

The expansion of SECONDS gives you not the assigned value, but the difference between the numbers of seconds since the assignment and the assigned value. The effect is like a variable whose value is incremented by 1 each second.

Time condition loop in shell

The best way to do this is using the $SECONDS variable, which has a count of the time that the script (or shell) has been running for. The below sample shows how to run a while loop for 3 seconds.

#! /bin/bash
end=$((SECONDS+3))

while [ $SECONDS -lt $end ]; do
# Do what you want.
:
done

Run a loop in bash with timeout in a single line

A command like

 while true ; do echo $(( i++ )) ; sleep 5 ; done

will produce output like

 0
1
2
3

But if I try to use that command directly in timeout, I get similar error messages, i.e.

timeout 20 while true ; do echo $(( i++ )) ; sleep 5 ; done

bash: syntax error near unexpected token do

Some programs (ssh for example), will process long strings of logic, if quoted so the argument is all one string.

timeout 20 "while true ; do echo $(( i++ )) ; sleep 5 ; done"

timeout: failed to run command 'while true ; do ...'

same error msg whether I use single of dbl-quotes to pass in string.

Reading info timeout we see that

 COMMAND must not be a special built-in utility (*note Special built in utilities::).

Maybe while loops qualify as special built-in utility?

Finally, note that I have removed worrying about does using the "wrapper" information you have, ie.

export TIMEOUT=60
export BLOCK_SIZE=65536
COMMAND="timeout TIMEOUT while ....

as an cause of your problem.

When you have a problem like this, it is better to prove to yourself that your command is working in a simpler case and then get it work inside a more complex usage.

Given this evidence, I don't think timeout is designed to do what you want.

As a last resort, I recommend that you try converting that while loop into a script and calling just

 timeout 20 myLooperScript

IHTH

Retry a Bash command with timeout

You can simplify things a bit by putting command right in the test and doing increments a bit differently. Otherwise the script looks fine:

NEXT_WAIT_TIME=0
until [ $NEXT_WAIT_TIME -eq 5 ] || command; do
sleep $(( NEXT_WAIT_TIME++ ))
done
[ $NEXT_WAIT_TIME -lt 5 ]

Stop dd inside a while loop after seconds

Adding my comment as an answer for completeness:

To stop a process after a given amount of time, you can run it using timeout if your system provides it; it is part of the GNU coreutils (but apparently not specified by POSIX).

In your case, instead of your loop, you could run

timeout "$c" dd if=/dev/zero of/dev/null

Bash script for do loop that detects a time period elapsed and then continues

Try to use the timeout program for that:

Usage:

timeout [OPTION] DURATION COMMAND [ARG]...

E.g. time (timeout 3 sleep 5) will run for 3 secs.
So in your code you can use:

timeout 300 scp -o StrictHostKeyChecking=no $BACKUP:* .

This limits the copy to 5 minutes.



Related Topics



Leave a reply



Submit