system-admin intermediate

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 $interval hold single values, while arrays @array and hashes %hash are 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_runs times to guarantee termination and quick completion.
  • $next_run sets 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 localtime converts 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

Tip: edit code and use “Run (Browser)”. Server runs always execute the published, verified snippet.
STDOUT
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.
STDERR
(empty)

Was this helpful?

Related Questions