Linux administrators and power users often need to run commands repeatedly. Whether you’re monitoring system performance, tracking log changes, or automating routine tasks, the ability to repeat a command at a specified interval is essential.
While cron has been a traditional tool, its minimum resolution is one minute—which can be too slow for real-time applications. In this guide, we explore multiple techniques to repeat commands every X seconds using built-in utilities like watch, flexible shell loops with sleep, built-in repeat commands in some shells, and modern scheduling with systemd timers. We also cover advanced drift compensation techniques to ensure precise intervals.
Table of Contents
Method 1: Using the watch
Command
The watch command is a simple and powerful utility that executes a given command at fixed intervals. It clears the terminal screen and updates the output, making it ideal for real-time monitoring.
Basic Usage
To run a command every X seconds, use:
watch -n X <command>
Example: Monitor free memory every 5 seconds:
watch -n 5 free -m
Enhancing the Output
- Highlight Differences:
Use the-d
flag to highlight changes between updates:watch -d -n 5 free -m
- Hide the Header:
Use the-t
option to remove the header (showing the interval, command, and current time):watch -t -n 5 free -m
- Multiple Commands:
For commands with pipes or special characters, wrap them in quotes:watch -n 5 'ps aux | grep firefox'
Use Cases for watch
- System Monitoring: See system load, memory usage, or process details quickly.
- Log Viewing: Monitor changes in log files, for example:
watch -n 2 'tail -n 20 /var/log/syslog'
Note: ‘watch’ clears the screen each time it updates. A shell loop might be a better option if you need a persistent history.
Read: Task scheduling on Linux: CRONTAB
Method 2: Using a Shell Loop with sleep
Shell loops provide flexibility, especially when you want to log outputs, run multiple commands, or avoid screen clearing. They are written using simple Bash scripting.
Basic Infinite Loop
A simple loop to run a command every X seconds:
while true; do
<command>
sleep X
done
Example: Display the current date every 5 seconds:
while true; do
date
sleep 5
done
One-Liner Versions
You can condense the loop into a one-liner:
while true; do date; sleep 5; done
Or place sleep in the condition:
while sleep 5; do date; done
This version waits 5 seconds before the first command execution.
Read: How to tweet from the Linux Command Line
Loop with a Fixed Number of Iterations
If you want the command to run a specific number of times:
for i in {1..10}; do
echo "Iteration $i: $(date)"
sleep 5
done
Avoiding Time Drift
When the command takes noticeable time to run, the overall cycle can drift. To adjust for this, calculate the command’s duration:
while true; do
start=$(date +%s)
<command>
duration=$(($(date +%s) - start))
sleep_time=$(( X - duration ))
[ $sleep_time -gt 0 ] && sleep $sleep_time
done
Example: Repeat a command every 5 seconds:
while true; do
start=$(date +%s)
echo "Current time:" $(date)
duration=$(($(date +%s) - start))
sleep_time=$(( 5 - duration ))
[ $sleep_time -gt 0 ] && sleep $sleep_time
done
This method helps maintain a consistent interval by compensating for the command’s run time.
Use Cases for Shell Loops
- Background Logging: Redirect output to a file to keep a history.
- Complex Operations: Chain multiple commands or include conditional logic.
- Real-Time Monitoring: Log system metrics or script outputs precisely without losing previous results.
Method 3: Using the Built-In repeat
Command in Certain Shells
Some shells like csh, tcsh, and zsh offer a built-in repeat command. This command is not available in Bash, but if you use one of these shells, you can leverage it.
Example in csh or tcsh
To repeat a command 5 times:
repeat 5 echo "Hello, world!"
To introduce a delay, combine it with a loop:
foreach i (`seq 1 5`)
echo "Hello, world!"
sleep 2
end
This method is shell-specific and useful if you prefer these environments.
Read: How to use systemd to troubleshoot Linux problems
Method 4: Scheduling Tasks with systemd Timers
For robust scheduling that persists across reboots and offers finer control than cron, systemd timers are an excellent choice. They use dedicated unit files to define when and how tasks should run.
How systemd Timers Work
A systemd timer consists of two unit files:
- A .timer file that schedules when the task should run.
- A corresponding .service file that defines the command to execute.
Creating Monotonic Timers
Monotonic timers use relative time (e.g., after boot or after the last execution).
Example: Run a Task 10 Minutes After Boot
Create /etc/systemd/system/example.timer
:
[Unit]
Description=Run example task 10 minutes after boot
[Timer]
OnBootSec=10min
Unit=example.service
[Install]
WantedBy=timers.target
And /etc/systemd/system/example.service
:
[Unit]
Description=Example Service
[Service]
Type=oneshot
ExecStart=/usr/local/bin/example-script.sh
Activate it with:
sudo systemctl enable --now example.timer
Read: How to Manage Ubuntu Boot Services: List, Start, and Stop Systemd Services at Startup
Creating Realtime Timers
Realtime timers use calendar scheduling with the OnCalendar keyword.
Example: Daily Task at Midnight
Create /etc/systemd/system/daily-task.timer
:
[Unit]
Description=Daily task at midnight
[Timer]
OnCalendar=daily
Persistent=true
Unit=daily-task.service
[Install]
WantedBy=timers.target
And /etc/systemd/system/daily-task.service
:
[Unit]
Description=Daily Task Service
[Service]
Type=oneshot
ExecStart=/usr/local/bin/daily-script.sh
Enable with:
sudo systemctl enable --now daily-task.timer
The Persistent=true option ensures that missed tasks (e.g., when the system is off) are executed immediately upon reboot.
Transient Timers with systemd-run
For temporary scheduling without creating persistent files, use systemd-run:
systemd-run --user --on-calendar '*:0/1' /bin/sh -c "date >> ~/log.txt"
This command creates temporary timer and service units that run every minute. Stop them using:
systemctl --user stop <transient-timer-name>.timer
Listing and Managing Timers
To list active timers:
systemctl list-timers
Inspect a timer’s configuration:
systemctl cat daily-task.timer
Stop a timer:
sudo systemctl stop daily-task.timer
Use Cases for systemd Timers
- Persistent Automation: Run maintenance scripts, backups, or updates reliably across reboots.
- Precise Calendar Scheduling: Schedule tasks at exact times or dates.
- Transient Tasks: Quickly set up one-off tasks without permanent configuration files.
Read: How to clear systemd journal Logs
Method 5: Running Commands Periodically with anacron
Anacron is ideal for desktop or laptop systems that are not always on. Unlike cron, which runs as a daemon on continuously running systems, anacron runs tasks that should occur at least once per day, even if the system was off during the scheduled time.
What is anacron?
Anacron reads a configuration file called anacrontab, which specifies tasks, their frequency (in days), and a delay before running. It is designed for systems that do not run 24/7.
Installing anacron
On Debian-based systems:
On Fedora or RHEL-based systems:
On Arch Linux, you might need to install cronie as anacron is not installed by default.
The anacrontab File
The anacrontab file is usually located at /etc/anacrontab. Its structure is as follows:
- Frequency in days
- Delay in minutes
- Job identifier
- Command to execute
Example anacrontab entry:
This runs the daily cron jobs with a delay of 5 minutes.
Running anacron as a Non-Privileged User
For desktops or laptops, you can set up a per-user anacron:
-
Create a local anacrontab:
-
Edit your local anacrontab as needed (e.g., change MAILTO or add custom jobs).
-
Schedule anacron to run hourly by adding this line to your personal crontab (
crontab -e
):
Use Cases for anacron
- Desktop/Laptop Scheduling: Run maintenance tasks on systems that are not always running.
- Ensuring Daily Tasks: Guarantee that a task runs at least once per day, regardless of downtime.
- User-Specific Automation: Allow non-privileged users to manage their own scheduled tasks.
Advanced Techniques for Accurate Scheduling
For scenarios where even a small timing drift is unacceptable, you can build advanced loops that calculate the elapsed time using Unix timestamps. For example:
PERIOD=5
while true; do
start=$(date +%s)
<command>
duration=$(($(date +%s) - start))
sleep_time=$(( PERIOD - duration ))
if [ $sleep_time -gt 0 ]; then
sleep $sleep_time
else
echo "Warning: Command took longer than the period of $PERIOD seconds!"
fi
done
This script ensures that the command runs as close as possible to every 5 seconds and warns if the command execution overruns the desired interval.
When to Use Which Method
- Watch or Shell Loops: Best for quick, session-based monitoring and when you need to see a history of outputs. They are ideal for tasks like monitoring system metrics or checking file changes.
- Systemd Timers: Use them for critical tasks that must run reliably even after reboots or when precise scheduling is required. They are more robust than cron for sub-minute tasks.
- Built-In Repeat (csh/tcsh/zsh): Use these if you work in shells that support them and need a quick way to repeat commands a fixed number of times.
- Anacron: Perfect for desktops and laptops that are not always on, ensuring that essential daily tasks run even if the system was off at the scheduled time.
Conclusion
Repeating Linux commands at specific intervals is a versatile skill that enhances real-time monitoring and task automation. Whether you choose the simplicity of the watch command, the flexibility of shell loops with sleep, the built-in repeat functions of certain shells, or the robust scheduling capabilities of systemd timers, or anacron, you now have multiple methods to suit any scenario.
By understanding these techniques and their use cases, you can ensure that your system management tasks run exactly when needed—whether for troubleshooting, performance monitoring, or automating routine processes. Experiment with these methods and tailor them to your environment for optimal results.
If you like the content, we would appreciate your support by buying us a coffee. Thank you so much for your visit and support.