, Job Scheduling, tutorial, guide, documentation, dargslan"> - Job Scheduling Guide"> ">

How to create on‑calendar job → systemd-run --on-calendar="Mon *-*-* 09:00"

How to Create On-Calendar Jobs with systemd-run --on-calendar Command Table of Contents 1. [Introduction](#introduction) 2. [Prerequisites](#prerequisites) 3. [Understanding systemd-run and On-Calendar Scheduling](#understanding-systemd-run-and-on-calendar-scheduling) 4. [Basic Syntax and Command Structure](#basic-syntax-and-command-structure) 5. [Calendar Event Format Explained](#calendar-event-format-explained) 6. [Step-by-Step Guide to Creating On-Calendar Jobs](#step-by-step-guide-to-creating-on-calendar-jobs) 7. [Practical Examples and Use Cases](#practical-examples-and-use-cases) 8. [Advanced Configuration Options](#advanced-configuration-options) 9. [Managing and Monitoring Scheduled Jobs](#managing-and-monitoring-scheduled-jobs) 10. [Troubleshooting Common Issues](#troubleshooting-common-issues) 11. [Best Practices and Professional Tips](#best-practices-and-professional-tips) 12. [Comparison with Other Scheduling Methods](#comparison-with-other-scheduling-methods) 13. [Conclusion](#conclusion) Introduction The `systemd-run` command with the `--on-calendar` option provides a powerful and flexible way to schedule jobs on Linux systems using systemd. Unlike traditional cron jobs, systemd calendar events offer more precise timing control, better logging integration, and enhanced system resource management. This comprehensive guide will teach you how to create, manage, and troubleshoot on-calendar jobs using the systemd-run command. By the end of this article, you'll understand how to schedule tasks with various time patterns, from simple daily routines to complex scheduling scenarios. You'll also learn best practices for system administration and automation using systemd's built-in scheduling capabilities. Prerequisites Before diving into on-calendar job creation, ensure you have the following: System Requirements - Linux distribution with systemd (most modern distributions) - systemd version 220 or later (for full --on-calendar support) - Root or sudo privileges for system-wide jobs - Basic command-line knowledge Verification Commands Check your systemd version: ```bash systemctl --version ``` Verify systemd-run availability: ```bash which systemd-run ``` Test basic systemd functionality: ```bash systemctl status ``` Knowledge Prerequisites - Basic understanding of Linux command line - Familiarity with systemd concepts - Understanding of time formats and scheduling concepts Understanding systemd-run and On-Calendar Scheduling What is systemd-run? The `systemd-run` command allows you to run programs in transient scope units, service units, or timer units. When combined with the `--on-calendar` option, it creates temporary timer units that execute commands at specified times. Key Advantages Over Cron 1. Better Integration: Native systemd integration with improved logging 2. Resource Management: Built-in resource control and isolation 3. Flexible Timing: More precise and flexible time specifications 4. System Dependencies: Can depend on system states and services 5. Centralized Management: Unified management through systemctl How On-Calendar Scheduling Works When you use `systemd-run --on-calendar`, systemd creates: - A transient timer unit that defines when to run - A transient service unit that defines what to run - Automatic cleanup after execution Basic Syntax and Command Structure Standard Command Format ```bash systemd-run --on-calendar="CALENDAR_EVENT" [OPTIONS] COMMAND [ARGUMENTS] ``` Essential Components - `systemd-run`: The base command - `--on-calendar="..."`: Specifies when to run - `COMMAND`: The command or script to execute - `[OPTIONS]`: Additional systemd-run options - `[ARGUMENTS]`: Arguments for the command Simple Example Breakdown ```bash systemd-run --on-calendar="Mon --* 09:00" /usr/bin/backup-script.sh ``` This command: - Runs every Monday at 9:00 AM - Executes the backup script - Creates temporary systemd units - Provides systemd logging and management Calendar Event Format Explained Basic Format Structure The calendar event format follows this pattern: ``` DayOfWeek Year-Month-Day Hour:Minute:Second ``` Component Breakdown Day of Week - `Mon`, `Tue`, `Wed`, `Thu`, `Fri`, `Sat`, `Sun` - Can be abbreviated: `Mo`, `Tu`, `We`, `Th`, `Fr`, `Sa`, `Su` - Multiple days: `Mon,Wed,Fri` or `Mon..Fri` Date Components - Year: Four digits (2024) or `*` for any year - Month: 01-12 or `*` for any month - Day: 01-31 or `*` for any day Time Components - Hour: 00-23 in 24-hour format - Minute: 00-59 - Second: 00-59 (optional) Wildcard and Range Examples ```bash Every day at 2:30 PM "--* 14:30" Every Monday at 9 AM "Mon --* 09:00" Weekdays at 8 AM "Mon..Fri --* 08:00" Every 15 minutes "*:0/15" First day of every month at midnight "--01 00:00" ``` Step-by-Step Guide to Creating On-Calendar Jobs Step 1: Plan Your Scheduling Requirements Before creating the job, determine: - When: Exact timing requirements - What: Command or script to execute - Where: Working directory requirements - Who: User context (root or specific user) - How: Any special environment needs Step 2: Test Your Command Manually Always test your command before scheduling: ```bash Test the actual command first /path/to/your/script.sh Verify it works as expected echo $? ``` Step 3: Create Your First On-Calendar Job Basic Example: Daily Backup ```bash systemd-run --on-calendar="daily" \ --unit=daily-backup \ /usr/local/bin/backup-script.sh ``` With Specific Timing ```bash systemd-run --on-calendar="Mon --* 09:00" \ --unit=monday-maintenance \ /usr/local/bin/system-maintenance.sh ``` Step 4: Verify Job Creation Check if the timer was created: ```bash systemctl list-timers --all | grep monday-maintenance ``` View timer details: ```bash systemctl status monday-maintenance.timer ``` Step 5: Monitor Job Execution Check service logs: ```bash journalctl -u monday-maintenance.service ``` View timer logs: ```bash journalctl -u monday-maintenance.timer ``` Practical Examples and Use Cases Example 1: System Maintenance Tasks Weekly System Updates ```bash systemd-run --on-calendar="Sun --* 02:00" \ --unit=weekly-updates \ --description="Weekly system updates" \ /usr/bin/apt update && /usr/bin/apt upgrade -y ``` Daily Log Rotation ```bash systemd-run --on-calendar="daily" \ --unit=log-rotation \ --working-directory=/var/log \ /usr/sbin/logrotate /etc/logrotate.conf ``` Example 2: Backup Operations Database Backup Every 6 Hours ```bash systemd-run --on-calendar="--* 00,06,12,18:00" \ --unit=database-backup \ --setenv=BACKUP_DIR=/backup/db \ /usr/local/bin/db-backup.sh ``` Weekly Full Backup ```bash systemd-run --on-calendar="Sat --* 23:00" \ --unit=full-backup \ --nice=19 \ --ioprio=3 \ /usr/local/bin/full-system-backup.sh ``` Example 3: Monitoring and Alerts Hourly Disk Space Check ```bash systemd-run --on-calendar="hourly" \ --unit=disk-space-check \ /usr/local/bin/check-disk-space.sh ``` Daily Security Scan ```bash systemd-run --on-calendar="--* 01:30" \ --unit=security-scan \ --timeout=3600 \ /usr/bin/rkhunter --check --skip-keypress ``` Example 4: Development and Deployment Nightly Build Process ```bash systemd-run --on-calendar="--* 02:00" \ --unit=nightly-build \ --uid=builduser \ --gid=buildgroup \ --working-directory=/home/builduser/project \ /usr/local/bin/nightly-build.sh ``` Certificate Renewal Check ```bash systemd-run --on-calendar="--01 03:00" \ --unit=cert-renewal \ --remain-after-exit \ /usr/bin/certbot renew --quiet ``` Advanced Configuration Options Resource Management Options CPU and Memory Limits ```bash systemd-run --on-calendar="daily" \ --unit=resource-limited-job \ --property=CPUQuota=50% \ --property=MemoryLimit=512M \ /usr/local/bin/intensive-task.sh ``` I/O Priority Settings ```bash systemd-run --on-calendar="--* 03:00" \ --unit=low-priority-backup \ --nice=19 \ --ioprio=3 \ /usr/local/bin/backup.sh ``` Environment and Security Options Custom Environment Variables ```bash systemd-run --on-calendar="Mon --* 08:00" \ --unit=env-job \ --setenv=API_KEY=secret123 \ --setenv=LOG_LEVEL=INFO \ /usr/local/bin/api-sync.sh ``` Running as Different User ```bash systemd-run --on-calendar="daily" \ --unit=user-job \ --uid=webapp \ --gid=webapp \ --working-directory=/var/www/app \ /usr/local/bin/app-maintenance.sh ``` Dependency Management Service Dependencies ```bash systemd-run --on-calendar="--* 04:00" \ --unit=dependent-job \ --property=After=network-online.target \ --property=Wants=network-online.target \ /usr/local/bin/network-dependent-task.sh ``` Complex Calendar Expressions Multiple Time Specifications ```bash systemd-run --on-calendar="Mon,Wed,Fri --* 09:00,17:00" \ --unit=multi-time-job \ /usr/local/bin/periodic-task.sh ``` Interval-Based Scheduling ```bash systemd-run --on-calendar="*:0/30" \ --unit=every-30-minutes \ /usr/local/bin/frequent-check.sh ``` Managing and Monitoring Scheduled Jobs Listing Active Timers View all active timers: ```bash systemctl list-timers ``` Show all timers (including inactive): ```bash systemctl list-timers --all ``` Filter specific timers: ```bash systemctl list-timers --all | grep backup ``` Controlling Timer Units Start/Stop Timers ```bash Stop a timer systemctl stop monday-maintenance.timer Start a timer systemctl start monday-maintenance.timer Restart a timer systemctl restart monday-maintenance.timer ``` Enable/Disable Timers ```bash Enable timer to start at boot systemctl enable monday-maintenance.timer Disable timer systemctl disable monday-maintenance.timer ``` Monitoring Job Execution Real-time Log Monitoring ```bash Follow logs for a specific service journalctl -u monday-maintenance.service -f Show recent logs journalctl -u monday-maintenance.service --since "1 hour ago" ``` Checking Job Status ```bash View service status systemctl status monday-maintenance.service Check last execution time systemctl show monday-maintenance.timer -p LastTriggerUSec ``` Modifying Existing Jobs Changing Schedule To modify an existing job, you typically need to: 1. Stop the current timer 2. Create a new job with updated schedule 3. Remove the old timer unit ```bash Stop existing timer systemctl stop old-job.timer Create new job systemd-run --on-calendar="new-schedule" \ --unit=updated-job \ /path/to/command Clean up old unit (if needed) systemctl reset-failed old-job.service ``` Troubleshooting Common Issues Issue 1: Timer Not Executing Symptoms - Timer shows as active but job never runs - No logs in journal for the service Diagnosis Steps ```bash Check timer status systemctl status job-name.timer Verify calendar expression systemd-analyze calendar "your-calendar-expression" Check system time timedatectl status ``` Solutions ```bash Restart systemd-timesyncd if time is wrong systemctl restart systemd-timesyncd Reload systemd if units are corrupted systemctl daemon-reload Check for syntax errors in calendar expression systemd-analyze calendar "Mon --* 09:00" ``` Issue 2: Command Not Found or Permission Errors Symptoms - Service fails with "command not found" - Permission denied errors in logs Diagnosis ```bash Check service logs journalctl -u job-name.service Verify command path which command-name Check file permissions ls -la /path/to/script ``` Solutions ```bash Use full path to command systemd-run --on-calendar="daily" /usr/bin/full-path-to-command Fix script permissions chmod +x /path/to/script Run as appropriate user systemd-run --on-calendar="daily" --uid=username /path/to/script ``` Issue 3: Environment Variables Not Available Symptoms - Script fails because environment variables are missing - Commands work manually but fail when scheduled Solutions ```bash Set environment variables explicitly systemd-run --on-calendar="daily" \ --setenv=PATH=/usr/local/bin:/usr/bin:/bin \ --setenv=HOME=/root \ /path/to/script Source environment in script systemd-run --on-calendar="daily" \ /bin/bash -c "source /etc/environment && /path/to/script" ``` Issue 4: Jobs Running Multiple Times Symptoms - Same job appears to run multiple times - Duplicate entries in logs Diagnosis ```bash Check for duplicate timers systemctl list-timers | grep job-name Look for multiple units with same name systemctl list-units --all | grep job-name ``` Solutions ```bash Stop all related units systemctl stop job-name.* Reset failed states systemctl reset-failed Create single new job systemd-run --on-calendar="schedule" --unit=unique-name /command ``` Best Practices and Professional Tips Security Best Practices Principle of Least Privilege ```bash Run jobs as non-root when possible systemd-run --on-calendar="daily" \ --uid=serviceuser \ --gid=servicegroup \ /usr/local/bin/user-script.sh ``` Secure Script Permissions ```bash Set proper permissions on scripts chmod 750 /usr/local/bin/scheduled-script.sh chown root:admin /usr/local/bin/scheduled-script.sh ``` Resource Management Best Practices Resource Limits for Heavy Jobs ```bash systemd-run --on-calendar="--* 02:00" \ --unit=heavy-job \ --property=CPUQuota=25% \ --property=MemoryLimit=1G \ --property=IOWeight=100 \ --nice=19 \ /usr/local/bin/resource-intensive-task.sh ``` Timeout Configuration ```bash systemd-run --on-calendar="daily" \ --unit=timed-job \ --property=TimeoutSec=1800 \ /usr/local/bin/long-running-task.sh ``` Logging and Monitoring Best Practices Structured Logging ```bash Configure job with proper logging systemd-run --on-calendar="daily" \ --unit=logged-job \ --property=StandardOutput=journal \ --property=StandardError=journal \ --property=SyslogIdentifier=my-scheduled-job \ /usr/local/bin/task.sh ``` Log Retention ```bash Configure journal retention for job logs mkdir -p /etc/systemd/journald.conf.d/ echo -e "[Journal]\nMaxRetentionSec=30day" > /etc/systemd/journald.conf.d/retention.conf ``` Development and Testing Best Practices Testing Calendar Expressions ```bash Always test calendar expressions systemd-analyze calendar "Mon,Wed,Fri --* 09:00,17:00" Check next execution times systemd-analyze calendar "daily" --iterations=5 ``` Dry Run Testing ```bash Test command execution without scheduling systemd-run --no-block --unit=test-job /path/to/script Check immediate execution systemctl status test-job.service ``` Documentation and Maintenance Descriptive Unit Names ```bash Use descriptive unit names systemd-run --on-calendar="daily" \ --unit=daily-database-backup-production \ --description="Daily backup of production database" \ /usr/local/bin/db-backup.sh ``` Version Control for Scripts - Keep scheduled scripts in version control - Document schedule changes in commit messages - Use configuration management tools for deployment Performance Optimization Staggered Execution ```bash Avoid running all jobs at the same time Instead of: --* 02:00 Use staggered times: systemd-run --on-calendar="--* 02:15" --unit=job1 /cmd1 systemd-run --on-calendar="--* 02:30" --unit=job2 /cmd2 systemd-run --on-calendar="--* 02:45" --unit=job3 /cmd3 ``` Resource-aware Scheduling ```bash Schedule I/O intensive jobs during off-peak hours systemd-run --on-calendar="--* 03:00" \ --unit=backup-job \ --ioprio=3 \ --nice=19 \ /usr/local/bin/backup.sh ``` Comparison with Other Scheduling Methods systemd-run vs. Cron | Feature | systemd-run | Cron | |---------|-------------|------| | Integration | Native systemd | Separate daemon | | Logging | journald integration | Separate log files | | Resource Control | Built-in limits | Manual nice/ionice | | Dependencies | Service dependencies | None | | Flexibility | High precision timing | Limited precision | | Learning Curve | Steeper | Simpler | systemd-run vs. Persistent Timer Units | Aspect | systemd-run | Persistent Timers | |--------|-------------|-------------------| | Persistence | Transient | Persistent | | Boot Survival | No | Yes | | Configuration | Command-line | Unit files | | Complexity | Simple | More complex | | Use Case | Temporary/testing | Production systems | When to Use systemd-run Ideal for: - Quick testing of scheduled jobs - Temporary scheduling needs - One-off scheduled tasks - Development and prototyping Not ideal for: - Critical production jobs requiring persistence - Jobs that must survive reboots - Complex job dependencies - Jobs requiring detailed configuration Conclusion The `systemd-run --on-calendar` command provides a powerful and flexible way to schedule jobs on modern Linux systems. Throughout this guide, we've explored everything from basic syntax to advanced configuration options, practical examples, and troubleshooting techniques. Key Takeaways 1. Flexibility: systemd calendar events offer more precise timing control than traditional cron 2. Integration: Native systemd integration provides better logging and resource management 3. Simplicity: Quick command-line job creation without writing unit files 4. Monitoring: Built-in monitoring and logging through systemctl and journalctl 5. Resource Control: Advanced options for CPU, memory, and I/O management Next Steps To further develop your systemd scheduling skills: 1. Practice: Create test jobs with various calendar expressions 2. Monitor: Set up monitoring for your scheduled jobs 3. Document: Maintain documentation of your scheduled tasks 4. Explore: Learn about persistent systemd timer units for production use 5. Automate: Consider using configuration management tools to deploy scheduled jobs Final Recommendations - Start with simple schedules and gradually increase complexity - Always test commands manually before scheduling - Use descriptive unit names and descriptions - Implement proper logging and monitoring - Follow security best practices with appropriate user permissions - Consider resource limits for intensive tasks The `systemd-run --on-calendar` command bridges the gap between quick ad-hoc scheduling and full systemd timer unit implementation, making it an invaluable tool for system administrators and developers working with modern Linux systems. By mastering these techniques, you'll be able to create robust, well-monitored scheduled jobs that integrate seamlessly with your system's service management infrastructure. Remember that while systemd-run is excellent for temporary and testing scenarios, production environments may benefit from persistent systemd timer units that survive system reboots and provide more comprehensive configuration options. Use the knowledge gained here as a foundation for exploring the full capabilities of systemd's timing and scheduling features.