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
Difference Between Double and Single Bigger Than in Linux Terminal
What's The Best Way to Move a Directory into Place in a Makefile Install
Putting Extensions in a Certificate in Openssl
How to See Output to Stdout After Disown and Logout
Shell Script Not Running via Crontab, Runs Fine Manually
Tar: Cowardly Refusing to Create an Empty Archive
Why Does Sed Leave Many Files Around
Bash, Execute Command But Continue with Interactive Session
Ssh - Help Understanding Proxy Command
Linux Clipboard Read/Write in C
Different Memory Alignment for Different Buffer Sizes
Do I Get a Notification from Epoll When a Fd Is Closed
Possible to Assign a New Ip Address on Every Http Request
How to Kill a Whole Process Tree with Perl
Command or Option for The Xgettext, Msginit, Msgfmt Sequence for Setting The Mime Type