How CasaOS Manages Periodic Tasks Using Cron: Hardware Status Scheduling Explained

CasaOS uses the robfig/cron library with second-level precision to schedule background jobs, creating independent cron.Cron instances that execute functions like SendAllHardwareStatusBySocket every five seconds for real-time system monitoring without blocking the main HTTP server.

The IceWhaleTech/CasaOS repository implements a robust scheduling mechanism for recurring maintenance and monitoring operations. By leveraging the popular robfig/cron library, CasaOS can execute periodic tasks such as gathering CPU, memory, and network statistics while keeping the system responsive.

The Cron Architecture in CasaOS

CasaOS relies on the third-party robfig/cron library (specifically github.com/robfig/cron/v3) rather than the system crontab. This approach provides several advantages: Go-native execution, second-level scheduling precision, and safe concurrent job handling within the application process.

The architecture allows multiple independent cron instances across different packages. Each scheduler runs in its own goroutine, ensuring that hardware monitoring tasks never interfere with HTTP request handling or WebSocket communications.

Scheduling Hardware Status Updates

The primary periodic task in CasaOS involves collecting comprehensive hardware metrics and broadcasting them via the internal notification bus.

The Main Scheduler Setup

In main/main.go, the application initializes a global cron instance during startup:

crontab := cron.New(cron.WithSeconds())
if _, err := crontab.AddFunc("@every 5s", route.SendAllHardwareStatusBySocket); err != nil {
    logger.Error("add crontab error", zap.Error(err))
}
crontab.Start()

The cron.WithSeconds() option enables second-level precision, while the @every 5s schedule expression ensures the hardware status function executes every five seconds. The Start() method launches the scheduler in a background goroutine immediately.

The Hardware Monitoring Job

The actual data collection logic resides in route/periodical.go within the SendAllHardwareStatusBySocket() function. This job orchestrates system metric gathering through the SystemService interface:

func SendAllHardwareStatusBySocket() {
    // 1. Gather network interface statistics
    netList := service.MyService.System().GetNetInfo()
    // Interface state collection via GetNetState...
    
    // 2. Collect CPU metrics
    cpuPercent := service.MyService.System().GetCpuPercent()
    cpuCores := service.MyService.System().GetCpuCoreNum()
    cpuInfo := service.MyService.System().GetCpuInfo()
    cpuTemp := service.MyService.System().GetCPUTemperature()
    cpuPower := service.MyService.System().GetCPUPower()
    
    // 3. Retrieve memory statistics
    memInfo := service.MyService.System().GetMemInfo()
    
    // 4. Assemble payload
    body := map[string]interface{}{
        "sys_mem": memInfo,
        "sys_cpu": cpuData,
        "sys_net": newNet,
    }
    
    // 5. Publish to notification bus
    service.MyService.Notify().SendNotify("casaos:system:utilization", body)
}

The function aggregates data from multiple sources—including network interfaces via GetNetInfo, processor utilization via GetCpuPercent, and memory statistics via GetMemInfo—then publishes the payload under the topic casaos:system:utilization using the notification service.

Additional Periodic Tasks: WebSocket Heartbeat

CasaOS demonstrates architectural flexibility by allowing sub-packages to maintain their own schedulers. In route/v1/file.go, a separate cron instance manages WebSocket health checks:

func init() {
    go handler.monitoring()  // Start WebSocket client manager
    
    crontab := cron.New(cron.WithSeconds())
    task := func() { 
        handler.broadcast <- []byte(`{"type":"ping"}`) 
    }
    // Classic cron syntax: every 30 seconds
    crontab.AddFunc("*/30 * * * * ?", task)
    crontab.Start()
}

This pattern—using */30 * * * * ? cron syntax alongside the @every shorthand—shows that CasaOS supports standard cron expressions with seconds fields. Each independent scheduler handles its own lifecycle, preventing single points of contention.

Key Implementation Details

  • Second-level precision: The cron.WithSeconds() configuration option enables sub-minute scheduling, critical for real-time hardware monitoring.
  • Goroutine isolation: Each crontab.Start() invocation spawns a separate goroutine, ensuring periodic tasks never block the main application thread.
  • Service layer integration: Jobs interact with hardware through the service.System() interface, abstracting direct system calls into testable service methods.
  • Notification bus: Rather than tightly coupling to WebSocket handlers, the system uses service.MyService.Notify().SendNotify() for decoupled message distribution.

Summary

  • CasaOS uses the robfig/cron library for in-process task scheduling with second-level precision.
  • The main hardware status job runs every 5 seconds via @every 5s schedule in main/main.go.
  • route/periodical.go contains SendAllHardwareStatusBySocket(), which gathers CPU, memory, network, and temperature data through SystemService methods.
  • Multiple independent cron instances (e.g., in route/v1/file.go) allow fine-grained scheduling without contention.
  • Hardware metrics are published to the casaos:system:utilization topic via the notification bus for decoupled consumption.

Frequently Asked Questions

How does CasaOS prevent periodic tasks from blocking the main application?

CasaOS runs each cron scheduler in its own goroutine. When crontab.Start() is called, the library spawns a background goroutine that sleeps until the next scheduled execution time, leaving the main HTTP server and other services unblocked.

What cron library does CasaOS use for background jobs?

CasaOS uses github.com/robfig/cron/v3, a popular Go library that provides robust cron expression parsing, second-level precision, and thread-safe job execution. This replaces traditional system-level cron for in-application scheduling.

How often does CasaOS send hardware status updates?

According to the source code in main/main.go, CasaOS sends hardware status updates every 5 seconds using the @every 5s schedule expression. This provides near real-time monitoring of CPU, memory, and network utilization.

Where does CasaOS publish the collected hardware status data?

The SendAllHardwareStatusBySocket() function in route/periodical.go publishes data to the internal notification bus using service.MyService.Notify().SendNotify() with the topic casaos:system:utilization, allowing WebSocket handlers and other subscribers to receive updates without direct coupling to the monitoring logic.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →