This article describes how to repeat a command every X seconds on Linux in two ways:
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.
watch Each run one command
watch -n <X> <command>
-nSpecify time interval
XIs the time interval between running commands, in seconds (0.1 second is the smallest possible value)
commandIs the command you want to run
If the command contains pipes, quotation marks or other special characters, please use single quotation marks, for example:
example.The following command runs
ps aux | grep firefox Every 5 seconds:
watch -n 5 'ps aux | grep firefox'
watch The command has some options, such as highlighting the differences between successive updates (
-d), if the exit of the command is non-zero, a beep will sound (
-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
sleep in a
while Loop, repeat the command every X seconds
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
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 2020Thu 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
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
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)