Shell: is it possible to delay a command without using `sleep`?
Solution 1
You have alternatives to sleep
: They are at
and cron
. Contrary to sleep
these need you to provide the time at which you need them to run.
Make sure the
atd
service is running by executingservice atd status
.
Now let's say the date is 11:17 am UTC; if you need to execute a command at 11:25 UTC, the syntax is:echo "This is a test" | at 11:25
.
Now keep in mind thatatd
by default will not be logging the completion of the jobs. For more refer this link. It's better that your application has its own logging.You can schedule jobs in
cron
, for more refer :man cron
to see its options orcrontab -e
to add new jobs./var/log/cron
can be checked for the info on execution on jobs.
FYI sleep system call
suspends the current execution and schedules it w.r.t. the argument passed to it.
EDIT:
As @Gaius mentioned , you can also add minutes time to at
command.But lets say time is 12:30:30
and now you ran the scheduler with now +1 minutes
. Even though 1 minute, which translates to 60 seconds was specified , the at
doesn't really wait till 12:31:30
to execute the job, rather it executes the job at 12:31:00
. The time-units can be minutes, hours, days, or weeks
. For more refer man at
e.g: echo "ls" | at now +1 minutes
Solution 2
With bash
builtins, you can do:
coproc read -t 10 && wait "$!" || true
To sleep for 10 seconds without using sleep
. The coproc
is to make so that read
's stdin is a pipe where nothing will ever come out from. || true
is because wait
's exit status will reflect a SIGALRM delivery which would cause the shell to exit if the errexit
option is set.
In other shells:
mksh
and ksh93
have sleep
built-in, no point in using anything else there (though they both also support read -t
).
zsh
also supports read -t
, but also has a builtin wrapper around select()
, so you can also use:
zmodload zsh/zselect
zselect -t 1000 # centiseconds
If what you want is schedule things to be run from an interactive shell session, see also the zsh/sched
module in zsh
.
Solution 3
Some other ideas.
top -d10 -n2 >/dev/null
vmstat 10 2 >/dev/null
sar 10 1 >/dev/null
timeout 10s tail -f /dev/null
Solution 4
Since there are answers which are suggesting to use the non-standard -t delay
option of read
, here is a way to do a timed-out read in a standard shell:
{ ss=`stty -g`; stty -icanon min 0 time 20; read foo; stty "$ss"; }
The argument to stty time
is in tenths of second.
Solution 5
Using the bash built-in variable $SECONDS
and a busy-loop:
for((target=$((SECONDS + 10)); SECONDS < target; true)); do :; done
Related videos on Youtube
user321697
Updated on September 18, 2022Comments
-
user321697 over 1 year
Are there any substitutes, alternatives or bash tricks for delaying commands without using
sleep
? For example, performing the below command without actually using sleep:$ sleep 10 && echo "This is a test"
-
Admin over 5 yearsWhat's wrong with
sleep
? -
Admin over 5 yearsWhat do you want to wait for? If there’s an event you’re waiting for, you’d typically use a while loop, testing for the condition and sleeping for one second (or whatever makes sense). If you’re waiting for a child process to finish, then you can use the wait builtin. If it’s something else, do elaborate, please.
-
Admin over 5 years@user321697 “at” is to schedule single jobs. they are executed by the atd service, so they won’t pause your shell script. one use case for at would be to have it do something at a specified time (async) and create a marker file when it’s finished, while your script is waiting for that file to appear in a while loop. you could achieve a similar effect by scheduling a job to send your script a SIGCONT and then freezing your script by sending yourself a SIGSTOP.
-
Admin over 5 years
-
Admin over 5 years
-
Admin over 5 yearsI came here expecting everyone to suggest a spinlock. I'm pleasantly surprised by all the answers.
-
Admin over 5 yearsRe: "Curiosity" -- in unix.stackexchange.com/help/dont-ask, note the requirement that "You should only ask practical, answerable questions based on actual problems that you face." -- that this has been well-received despite controvening that guideline makes it a rather rare exception.
-
Admin over 5 years@CharlesDuffy the votes on this question most likely correlate with a visit from the HNQ; I agree that it's not a useful question in the current state.
-
Admin over 2 years@muru, you can't kill a sleeping process. Even using
kill -9
. -
Admin over 2 years@JamesBond I think you might be confusing run-of-the-mill sleeping processes with processes in uninterruptible sleep.
-
-
user321697 over 5 yearsThanks for this. Could you provide an example for performing a scheduled task (10 seconds from now) with
at
? -
Fabby over 5 yearsan edit and an upvote! ;-)
-
user321697 over 5 years
cron
store tasks incrontab
, right? Where doesat
store the scheduled data? -
Fabby over 5 years@user321697 Already answered here
-
ss_iwe over 5 yearsThis wont if the process needs to be run interaction free or in the background right?
-
Stéphane Chazelas over 5 yearsThat would in effect pause for a duration ranging somewhere in between 9 and 10 seconds though (due to a bug in
bash
;zsh
andmksh
had similar issues but have been fixed since) -
Jeff Schaller over 5 yearsWould you consider
read -t 10 < /dev/zero || true
? -
Stéphane Chazelas over 5 years@JeffSchaller I would avoid it as that's a busy loop.
-
ctrl-alt-delor over 5 yearsA good way to make heat.
-
ctrl-alt-delor over 5 yearsA good way to make heat.
-
Jeff Schaller over 5 yearswon't be the first time I'm accused of being full of hot air! :)
-
Nick over 5 years@StéphaneChazelas I wouldn't expect that to be a busy loop – I'd expect any shell's
read
to be implemented using select(2) or something similar (implying that read-with-timeout would be a good answer to this question). I'm expressing surprise rather than contradicting you, but can you point to further discussion of this? -
Stéphane Chazelas over 5 years@NormanGray,
/dev/zero
is a file that contains an infinite amount of data (NUL bytes). Soread
will read as much as it can during those 10 seconds. Thankfully, in the case ofbash
which doesn't support storing NUL bytes in its variables, that won't use up any memory, but that will still hog CPU resources. -
Stéphane Chazelas over 5 years@NormanGray, if run from a terminal,
/dev/stdout
would be the tty device, so it would have side effects (like stopping the script if run in background) and would return if the user presses enter for instance.read -t 10 /dev/stdout | :
would work on Linux, but on Linux only, whilecoproc
should work regardless of the OS. -
JVG over 5 yearsThis is not true, you can schedule an at job for say now +1 minute, to run in a minutes time
-
Peter Cordes over 5 yearsDelay-loops are a terrible idea for anything except the very shortest of sleeps (a couple nanoseconds or clock cycles in a device driver) on any modern CPU that can run a Unix-like OS. i.e. a sleep so short you can't usefully have the CPU do anything else while waiting, like schedule another process or enter a low-power sleep state before waking on a timer interrupt. Dynamic CPU-frequency makes it impossible to even calibrate a delay loop for counts per second, except as a minimum delay potentially sleeping a lot longer at low clock speeds before ramping up.
-
Peter Cordes over 5 yearsAncient computers had a power consumption that was much less dependent on workload. Modern CPUs need to dynamically power down different parts of the chip as much as possible to not melt (e.g. power down parts of the FPU or SIMD execution units while only integer code is running, or at least gate the clock signal to parts of the chip that don't need to be switching). And entering a low-power sleep state when idle (instead of spinning in an infinite loop waiting for timer interrupts) is also more recent than the ancient computers you mention.
-
Peter Cordes over 5 yearsFor more about CPU history, see Modern Microprocessors A 90-Minute Guide! - lighterra.com/papers/modernmicroprocessors.
-
Fabby over 5 yearsCorrect: But that was not one of the OP's requirements as per the original question, so still a valid answer... ;-) >:-)
-
Rui F Ribeiro over 5 yearsYou "stole" my idea of timelimit/timeout.... +1
-
spectras over 5 yearsFirewall or name system misconfiguration might introduce a significant additional delay tough.
-
AnoE over 5 yearsOP specifically gives an example (with
sleep
) and asks for an equivalent alternative without. Soread
doesn't parse, sorry. ;) -
AnoE over 5 years127.0.0.1 ... @spectras
-
Baldrickk over 5 yearsThankfully no longer needed, as Windows now supports sleep natively.
-
Fabby over 5 years@AnoE Stéphane's answer is of course the best, mine is just the oldest
--- press «enter» to continue ---
;-) -
spectras over 5 years@AnoE> solves the name system part, not the firewall part. Though not common, it can be configured to silently drop pings on local interface. That will cause ping to wait much longer.
-
A C over 5 years+1 for the "fond" memories
-
Francesco Belladonna about 5 yearsOhhhh my, thanks, I was in a situation without sleep, top is amazing!