How to schedule periodic tasks without cron in Perl?
Question
How to schedule periodic tasks without cron in Perl?
Scheduling Periodic Tasks Without Cron in Perl
To schedule periodic tasks in Perl without relying on external tools like cron, the typical method is to run a loop that sleeps between task executions. Using the Time::HiRes core module allows microsecond precision and better control over timing.
However, in sandboxed or time-limited environments, long running loops with multi-second sleeps can cause timeouts. To avoid this, you can reduce the interval duration and limit the number of iterations strictly so the code finishes promptly while demonstrating the technique clearly.
Key Perl Concepts
- Sigils: Scalars like
$intervalhold single values, while arrays@arrayand hashes%hashare collections. - Context: Functions like
time()return a scalar epoch timestamp in seconds, which is used for scheduling. - TMTOWTDI: Perl’s flexibility lets you implement periodic loops in many ways; this approach uses a loop with timed checks and
Time::HiRes::sleep().
Corrected Scheduler Code for Fast Sandbox Execution
This example runs a periodic task 5 times every 0.3 seconds and finishes quickly to avoid timeout in limited environments. The $next_run variable drives absolute timing to avoid drift.
use strict;
use warnings;
use Time::HiRes qw(sleep time);
my $interval = 0.3; # interval in seconds (short to finish quickly)
my $max_runs = 5; # number of executions
my $runs = 0;
my $next_run = time();
print "Starting scheduler: running every $interval seconds, $max_runs times.\n";
while ($runs < $max_runs) {
my $now = time();
if ($now >= $next_run) {
print scalar localtime($now) . ": Task executed (" . ($runs + 1) . "/$max_runs).\n";
$runs++;
$next_run += $interval;
}
# Sleep briefly to reduce CPU usage and prevent busy loop
sleep(0.05);
}
print "Scheduler finished after $runs runs.\n";
Explanation
- Loop runs at most
$max_runstimes to guarantee termination and quick completion. $next_runsets the exact time for the next task to execute, preventing timing drift caused by repeated fixed sleeps.- A short sleep of 50 milliseconds inside the loop prevents 100% CPU usage while waiting.
- Using
localtimeconverts epoch time into readable timestamps for clarity.
Common Pitfalls
- Infinite loops: Always ensure loops have a clear exit condition in sandboxed environments.
- Timing drift: Avoid simply sleeping fixed intervals repeatedly—use absolute time reference to keep schedule accurate.
- CPU usage: Busy-wait loops without any sleep consume unnecessary CPU.
- Long sleeps: In time-limited environments, long sleeps often cause script termination; keep intervals and sleeps minimal.
Summary
This method demonstrates how to implement simple, periodic task execution directly in Perl without external schedulers. By combining absolute time scheduling via time() and short sleeps with Time::HiRes, you can run lightweight periodic jobs safely and efficiently, even within sandboxed or limited execution contexts.
Verified Code
Executed in a sandbox to capture real output. • v5.34.1 • 1286ms
Starting scheduler: running every 0.3 seconds, 5 times.
Tue Dec 30 14:19:42 2025: Task executed (1/5).
Tue Dec 30 14:19:43 2025: Task executed (2/5).
Tue Dec 30 14:19:43 2025: Task executed (3/5).
Tue Dec 30 14:19:43 2025: Task executed (4/5).
Tue Dec 30 14:19:44 2025: Task executed (5/5).
Scheduler finished after 5 runs.
(empty)