This article describes how to repeat a command every X seconds on Linux in two ways: watch
And use sleep
in a while
Loop (to avoid time drift when using long-running commands).
watch
You can run the command repeatedly, displaying its output and errors (first screen). This allows you to observe changes in program output over time.
use watch
Each run one command X
second:
watch -n <X> <command>
where:
-
-n
Specify time interval -
X
Is the time interval between running commands, in seconds (0.1 second is the smallest possible value) -
command
Is the command you want to run
If the command contains pipes, quotation marks or other special characters, please use single quotation marks, for example: 'command'
.
example.The following command runs ps aux | grep firefox
Every 5 seconds:
watch -n 5 'ps aux | grep firefox'
of watch
The command has some options, such as highlighting the differences between successive updates ( --differences
/ -d
), if the exit of the command is non-zero, a beep will sound ( --beep
/ -b
), and more.Look at it Man page For more information.
You may also like: How to use find to find files modified in the last N days or minutes
use sleep
in a while
Loop, repeat the command every X seconds
Another way to repeat the command every X seconds on Linux is to use while
versus sleep
command:
while true; do <command>; sleep <X>; done
Here you need to replace command
And the command to run X
The time interval is in seconds (the number is not necessarily an integer, but it cannot be negative; you can also specify minutes-such as 1m, hours-such as 1h, etc.).
example.The following single line operation echo $(date)
Execute the command every 5 seconds:
while true; do echo $(date); sleep 5; done
If you are performing more complex operations, make sure the interval is shorter than the time required for the command to complete, otherwise this may interfere with some operations in the script.
Also note that with this command, time will drift, depending on how long the command you are running takes. For example, if you want to run a command every 5 seconds, but the command takes 3 seconds to complete, this will make the command run every 8 seconds instead of every 5 seconds.
One solution to avoid this time drift is to use the following method: Run the command every X seconds, regardless of how long it takes to complete the command (as long as the time it takes to complete the command does not exceed the sleep time).
while true; do <command>; sleep $((<X> - $(date +%s) % <X>)); done
Here, replace command
With the command you want to run, and X
The number of seconds in seconds after which the command should be repeated.
[[Edit]]This solution is not perfect. Read the explanation and alternative methods in markup editing later in this article.
example.Repeat the following line sleep 3
Command (I can’t think of a better example right now, this command takes a few seconds to complete, and it won’t cause damage without the user stopping-I’ll enter this command at 5 AM) every 5 seconds:
while true; do sleep 3; sleep $((5 - $(date +%s) % 5)); done
Even if the order ( sleep 3
In this case, it can be any command you want) takes 3 seconds to complete, and the interval between two runs is 5 seconds.
For testing, you can add a echo $(date)
It started like this:
while true; do echo $(date); sleep 3; sleep $((5 - $(date +%s) % 5)); done
You will notice that the date displayed in the terminal is in 5 second increments, as shown below:
Thu 10 Dec 05:48:00 2020
Thu 10 Dec 05:48:05 2020
Thu 10 Dec 05:48:10 2020
Thu 10 Dec 05:48:15 2020
[[Edit]]However, the solution is not perfect. Between the first and second run, the time interval may be shorter than the time interval you specify. However, subsequent runs use the correct time interval. If you know a better way, please leave a comment below.
[[Edit]]Solution (by Stack swap ), this can avoid time drift, and there is no problem I mentioned above (so, there is no different time interval between the first run and the second run), but it does not take advantage of sleep
The command is as follows:
while true; do currentTime=$(date +%s); elapsedTime=$((currentTime - lastTime)); if [ $elapsedTime -ge <X> ]; then <command>; lastTime=$currentTime; i=0; fi; done
replace X
The time interval (in seconds) between two runs, and command
With the command you want to repeat every X seconds.
Some explanation is needed here.This one while
The loop stores the current Unix time as currentTime
, And then subtract the last time ( lastTime
) From the current time, store it as elapsedTime
.Next, it checks whether the elapsed time is greater than or equal to X
If it is, it will run command
(Therefore, the command will X
second).Finally, it sets the last time equal to the current time, so it can be subtracted the next time it runs lastTime
From currentTime
, Which makes elapsedTime
value. I hope this makes sense to you, as it is in my head.
example.Repeat the following line echo $(date)
with sleep 2
Command (I used sleep 2
Therefore, the command takes a few seconds to complete every 5 seconds to be able to check whether the time is drifting:
while true; do currentTime=$(date +%s); elapsedTime=$((currentTime - lastTime)); if [ $elapsedTime -ge 5 ]; then echo $(date); sleep 2; lastTime=$currentTime; i=0; fi; done
You might also like: How to use find to delete files older than N days (with more examples)