I am running the timeout command of GNU Coreutils,
gtimeout 600 python myprogram.py
According to the manual,
duration is a floating point number followed by an optional unit:
‘s’ for seconds (the default) ‘m’ for minutes ‘h’ for hours ‘d’ for
days
Thus, the 'python myprogram.py part should terminate within 600 seconds (10 minutes). To my surprise, the command actually timeouts after 1 hour. Why?
It's possible that your program ignores SIGTERM, the signal which is used by gtimeout to "kindly ask the program to terminate".
You can have gtimeout use SIGKILL instead, which can't be ignored or blocked, by adding the parameter -s 9 like this:
gtimeout -s 9 python myprogram.py
Related
This question already has answers here:
Bash sleep in milliseconds
(3 answers)
Closed 2 years ago.
I am writing a bash script which simply needs to sleep for less than a second.
However 'sleep' only accepts seconds as input.
Is there any command to sleep less than 1000 ms?
sleep from GNU Core Utilities does accept decimal numbers. From sleep(1):
Pause for NUMBER seconds. SUFFIX may be s for seconds (the
default), m for minutes, h for hours or d for days. NUMBER
need not be an integer. Given two or more arguments, pause for the
amount of time specified by the sum of their values.
I also tested BusyBox version of sleep and confirmed that it also supports decimal numbers. This should clear any issues with even Alpine Linux.
The easiest workaround I could find is using bash's read builtin, which accepts milliseconds:
read -t 0.5
or with non bash scripts, for example fish:
bash -c 'read -t 0.5'
Can I configure bash to report how long each command takes to execute, if it's longer than some threshold?
I thought I recalled some setting for this, but can't find it either in bash(1) or google.
The idea, in case it's not clear, would be something like this:
% SUBCMDTMOUT=30
% sleep 29 # 29 seconds elapse
% sleep 30 # 30 seconds elapse
% sleep 31 # 31 seconds elapse
bash: subcommand `sleep 31' took 31 seconds to complete.
%
Prepend time to your command and then parse the output of time through any condition to get your desired output.
Example:
$ time sleep 15
real 0m15.003s
user 0m0.000s
sys 0m0.002s
#chepner probably has it right: REPORTTIME in zsh (though that only tracks CPU time; I suspect my mystery problem is some kind of network wait). But since I'm not motivated enough to convert my login shell for this, the specific answer to my question is "nope."
Is there a way to create a bash script that will only run for X hours? I'm currently setting up a cron job to initiate a script every night. This script essentially runs until a certain condition is met, exporting it's status to a holding variable to keep track of 'where it is' after each iteration. The intention is to start-up the process every night, run for a few hours, and then stop, holding the status until the process starts up the next night.
Short of somehow collecting the start time, and checking it against the current time in each iteration of the loop, is there an easier way to do this? Bash scripting is not my forte (I know enough to get things done and be dangerous) and I have not done something like this before. Any help would be appreciated. Thanks.
Use GNU Coreutils
GNU coreutils contains an actual timeout binary, usually invoked like this:
# timeout after 5 seconds when sleeping for 30
/usr/bin/timeout 5s /bin/sleep 30
In your case, you'd want to specify hours instead of seconds, so to timeout in 2 hours use something like 2h instead of 5s. See timeout(1) or info coreutils 'timeout invocation' for additional options.
Hacks and Workarounds
Native timeouts or the GNU timeout command are really the best options. However, see the following for some ideas if you decide to roll your own:
How do I run a command, and have it abort (timeout) after N seconds?
The TMOUT variable using read and process or command substitution.
Do it as you described - it is the cleanest way.
But if for some strange reason want kill the process after a time, can use the next
./long_runner &
(sleep 5; kill $!; wait; exit 0) &
will kill the long_runner after 5 secs.
By using the SIGALRM facility you can rig a signal to be sent after a certain time, but traditionally, this was not easily accessible from shell scripts (people would write small custom C or Perl programs for this). These days, GNU coreutils ships with a timeout command which does this by wrapping your command:
timeout 4h yourprogram
This question already has answers here:
Cron jobs and random times, within given hours
(13 answers)
Closed 9 years ago.
Need run a shell script once a day at random time. (so once every day between 00:00-23:59).
I know the sleep command, and the cron too, but
the cron has not random times
and the sleep solution - not very nice - my idea is launch the script every midnight and sleep random time at the start of the script.
Is here something more elegant?
If you have the at command, you can combinte the cron and the at.
Run from a cron every midnight the next script:
#!/bin/bash
script="/tmp/script.sh" #insert the path to your script here
min=$(( 24 * 60 ))
rmin=$(( $RANDOM % $min ))
at -f "$script" now+${rmin}min
The above will run the at command every midnight and will execute your script at random time . You should check your crontab how often is the atrun command started. (The atrun runs the commands stored with the at)
The main benefit in comparison with the sleep method: this "survives" the system reboot.
I would simply launch you script at midnight, and sleep for a random time between 0 and 86400 seconds. Since my bash's $RANDOM returns a number between 0 and 32767:
sleep $(( ($RANDOM % 1440)*60 + ($RANDOM % 60) ))
The best alternative to cron is probably at
See at man page
Usually, at reads commands from standard input, but you can give a file of jobs with -f.
Time wise, you can specify many formats. Maybe in your case the most convenient would be
at -f jobs now + xxx minutes
where your scripts gives xxx as a random value from 1 to 1440 (1440 minutes in a day), and jobs contains the commands you want to be executed.
Nothing prevents you from running sed to patch your crontab as the last thing your program does and just changing the next start time. I wouldn't sleep well though.
You can use cron to launch bash script, which generates pseudorandom timestamp and gives it to unix program at
I see you are familiar with bash and cron enough, so at will be a piece of cake for you. Documentation as always "man at" or you can try wiki
http://en.wikipedia.org/wiki/At_(Unix)
I'm not a scripting expert and I was wondering what was an acceptable way to run a script for at most x milliseconds (and yet finish before x milliseconds if the script is done before the timeout).
I solved that problem using Bash in a way that I think is very hacky and I wonder if there's a better way to do it.
Basically I've got one shell script called sleep_kill.sh that takes a PID as the first argument and a timeout as its second argument and that does this:
sleep $2
kill -9 $1 2> /dev/null 1> /dev/null
So if the PID corresponds to a script that finishes before timing out, nothing is going to be killed (I take it that the OS shall not have the time to be reusing this PID for another [unrelated] process seen that it's 'cycling' through all the process IDs before starting to reuse them).
Anyway, then I call my script that may "hang" or timeout:
command_that_may_hang.sh
PID=$!
sleep_kill.sh $PID .3
wait $PID > /dev/null 2>&1
And I'll be waiting at most 300 ms for command_that_may_hang.sh. Yet if command_that_may_hang.sh took only 10 ms to execute, I won't be "stuck" for 300 ms.
It would be great if some shell expert could explain the drawbacks of this approach and what should be done instead.
Have a look at this script: http://www.pixelbeat.org/scripts/timeout
Note timeouts of less that one second are pretty much nonsensical on most systems due to scheduling delays etc. Note also that newer coreutils has the timeout command included and it has a resolution of 1 second.