Task Scheduler in VyOS
The Task Scheduler in VyOS is a built-in system for scheduling and automatically running commands and scripts at specific times or at regular intervals. It is built on top of the system cron scheduler but provides a convenient configuration interface through the CLI.
Overview
The Task Scheduler lets you:
- Automate repetitive administrative tasks
- Run scheduled configuration backups
- Launch monitoring and diagnostic scripts
- Periodically clean up logs and temporary files
- Perform maintenance operations during off-hours
- Integrate with external systems through API calls
Capabilities
- Flexible scheduling: minutes, hours, days of the week, days of the month, months
- Cron-compatible syntax
- Execution of both VyOS operational commands and shell commands
- Integration with the logging system (syslog)
- Support for scripts (bash, python)
Schedule Syntax
The Task Scheduler uses standard cron syntax with five fields:
* * * * *
│ │ │ │ │
│ │ │ │ └─── Day of week (0-7, where 0 and 7 = Sunday)
│ │ │ └───── Month (1-12)
│ │ └─────── Day of month (1-31)
│ └───────── Hour (0-23)
└─────────── Minute (0-59)Special Characters
| Character | Description | Example |
|---|---|---|
* | Any value | * * * * * - every minute |
, | List of values | 0,15,30,45 * * * * - at 0, 15, 30, and 45 minutes of every hour |
- | Range of values | 0 9-17 * * * - every hour from 9:00 to 17:00 |
/ | Step (interval) | */5 * * * * - every 5 minutes |
*/n | Every n units | 0 */2 * * * - every 2 hours |
Schedule Examples
# Every minute
* * * * *
# Every 5 minutes
*/5 * * * *
# Every hour at minute 0
0 * * * *
# Daily at 2:30 AM
30 2 * * *
# Every Monday at 9:00 AM
0 9 * * 1
# First day of every month at midnight
0 0 1 * *
# Every 15 minutes during business hours (9-17) on weekdays
*/15 9-17 * * 1-5
# Every Sunday at 3:00 AM
0 3 * * 0Basic Configuration
Creating a Task
# General syntax
set system task-scheduler task <task-name> interval <cron-expression>
set system task-scheduler task <task-name> executable path <command/script>
# Example: daily configuration backup at 2:00 AM
set system task-scheduler task backup-config interval '0 2 * * *'
set system task-scheduler task backup-config executable path '/config/scripts/backup.sh'
commit
saveRunning VyOS Operational Commands
# Save the configuration every hour
set system task-scheduler task save-config interval '0 * * * *'
set system task-scheduler task save-config executable path '/opt/vyatta/sbin/vyatta-save-config.pl'
commit
saveRunning Shell Commands
# Clean up old logs once a day
set system task-scheduler task cleanup-logs interval '0 3 * * *'
set system task-scheduler task cleanup-logs executable path '/usr/bin/find /var/log -name "*.gz" -mtime +30 -delete'
commit
saveTasks with Arguments
# Script with parameters
set system task-scheduler task monitor-bandwidth interval '*/10 * * * *'
set system task-scheduler task monitor-bandwidth executable path '/config/scripts/bandwidth-monitor.sh'
set system task-scheduler task monitor-bandwidth executable arguments 'eth0 eth1'
commit
saveAdvanced Configuration
Backing Up the Configuration to a Remote Server
# Create the backup task
configure
set system task-scheduler task remote-backup interval '0 2 * * *'
set system task-scheduler task remote-backup executable path '/config/scripts/remote-backup.sh'
commit
saveContents of /config/scripts/remote-backup.sh:
#!/bin/bash
# Configuration
BACKUP_SERVER="192.168.1.100"
BACKUP_USER="backup"
BACKUP_DIR="/backups/vyos"
HOSTNAME=$(hostname)
DATE=$(date +%Y%m%d-%H%M%S)
BACKUP_FILE="config-${HOSTNAME}-${DATE}.boot"
# Save the current configuration
/opt/vyatta/sbin/vyatta-save-config.pl /tmp/${BACKUP_FILE}
# Copy to the remote server over SCP
scp -i /config/auth/backup-key /tmp/${BACKUP_FILE} ${BACKUP_USER}@${BACKUP_SERVER}:${BACKUP_DIR}/
# Clean up the local file
rm -f /tmp/${BACKUP_FILE}
# Logging
logger -t remote-backup "Configuration backed up to ${BACKUP_SERVER}"
# Remove old backups (older than 30 days) on the remote server
ssh -i /config/auth/backup-key ${BACKUP_USER}@${BACKUP_SERVER} \
"find ${BACKUP_DIR} -name 'config-${HOSTNAME}-*.boot' -mtime +30 -delete"Make the script executable:
sudo chmod +x /config/scripts/remote-backup.shMonitoring and Alerts
# Check the availability of critical services every 5 minutes
set system task-scheduler task service-monitor interval '*/5 * * * *'
set system task-scheduler task service-monitor executable path '/config/scripts/service-monitor.sh'
commit
saveContents of /config/scripts/service-monitor.sh:
#!/bin/bash
# List of services to check
SERVICES=("ssh" "dhcpd")
# Email for alerts
ALERT_EMAIL="admin@example.com"
# Check each service
for service in "${SERVICES[@]}"; do
if ! systemctl is-active --quiet "$service"; then
# Service is not running - send an alert
echo "ALERT: Service $service is not running on $(hostname)" | \
mail -s "VyOS Service Alert" $ALERT_EMAIL
# Logging
logger -t service-monitor -p user.err "Service $service is not running"
# Attempt to restart
systemctl restart $service
if systemctl is-active --quiet "$service"; then
logger -t service-monitor -p user.notice "Service $service restarted successfully"
fi
fi
doneCleaning Up Old Logs and Temporary Files
# Weekly cleanup on Sunday at 4:00 AM
set system task-scheduler task weekly-cleanup interval '0 4 * * 0'
set system task-scheduler task weekly-cleanup executable path '/config/scripts/cleanup.sh'
commit
saveContents of /config/scripts/cleanup.sh:
#!/bin/bash
# Remove old compressed logs (older than 60 days)
find /var/log -name "*.gz" -mtime +60 -delete
# Remove old core dumps
find /var/core -type f -mtime +7 -delete
# Clean up temporary files older than 7 days
find /tmp -type f -mtime +7 -delete
# Clean up old DHCP leases
# (caution: may need to be adjusted for your environment)
# find /var/lib/dhcp -name "*.leases~" -mtime +30 -delete
# Logging
logger -t weekly-cleanup "Weekly cleanup completed"API Integration with External Systems
# Send metrics to the monitoring system every 15 minutes
set system task-scheduler task send-metrics interval '*/15 * * * *'
set system task-scheduler task send-metrics executable path '/config/scripts/send-metrics.sh'
commit
saveContents of /config/scripts/send-metrics.sh:
#!/bin/bash
# Configuration
MONITORING_SERVER="http://monitoring.example.com:8086"
INFLUXDB_TOKEN="your-token-here"
HOSTNAME=$(hostname)
# Collect metrics
CPU_LOAD=$(uptime | awk -F'load average:' '{print $2}' | awk '{print $1}' | tr -d ',')
MEM_USAGE=$(free | awk '/Mem:/ {printf "%.2f", ($3/$2)*100}')
DISK_USAGE=$(df -h / | awk '/\// {print $5}' | tr -d '%')
# Send to InfluxDB
curl -X POST "${MONITORING_SERVER}/write?db=network_devices" \
-H "Authorization: Token ${INFLUXDB_TOKEN}" \
--data-binary "cpu_load,host=${HOSTNAME} value=${CPU_LOAD}
memory_usage,host=${HOSTNAME} value=${MEM_USAGE}
disk_usage,host=${HOSTNAME} value=${DISK_USAGE}"
# Logging
logger -t send-metrics "Metrics sent to monitoring server"Configuration Rotation with Git
# Daily commit of the configuration to a Git repository
set system task-scheduler task git-backup interval '0 1 * * *'
set system task-scheduler task git-backup executable path '/config/scripts/git-backup.sh'
commit
saveContents of /config/scripts/git-backup.sh:
#!/bin/bash
# Git configuration
GIT_REPO="/config/git-backup"
CONFIG_FILE="/config/config.boot"
HOSTNAME=$(hostname)
# Initialize the repository (if needed)
if [ ! -d "${GIT_REPO}/.git" ]; then
mkdir -p ${GIT_REPO}
cd ${GIT_REPO}
git init
git config user.email "vyos@${HOSTNAME}"
git config user.name "VyOS Task Scheduler"
fi
cd ${GIT_REPO}
# Copy the current configuration
cp ${CONFIG_FILE} ${GIT_REPO}/config.boot
# Commit the changes
git add config.boot
git commit -m "Automated backup on $(date '+%Y-%m-%d %H:%M:%S')"
# Push to the remote repository (optional)
# git push origin main
# Logging
logger -t git-backup "Configuration committed to Git"Checking VPN Tunnels
# Check IPsec tunnels every 10 minutes
set system task-scheduler task check-vpn interval '*/10 * * * *'
set system task-scheduler task check-vpn executable path '/config/scripts/check-vpn.sh'
commit
saveContents of /config/scripts/check-vpn.sh:
#!/bin/bash
# List of peers to check
PEERS=("site-b" "site-c")
# Email for alerts
ALERT_EMAIL="network-ops@example.com"
# Check each peer
for peer in "${PEERS[@]}"; do
# Check the tunnel state
STATUS=$(vtysh -c "show vpn ipsec sa" | grep -c "ESTABLISHED")
if [ "$STATUS" -eq 0 ]; then
# Tunnel is not established
echo "VPN tunnel to ${peer} is DOWN on $(hostname) at $(date)" | \
mail -s "VPN Alert: ${peer}" $ALERT_EMAIL
logger -t check-vpn -p user.err "VPN tunnel to ${peer} is DOWN"
# Attempt to restart
sudo ipsec restart
sleep 10
# Re-check
STATUS_AFTER=$(vtysh -c "show vpn ipsec sa" | grep -c "ESTABLISHED")
if [ "$STATUS_AFTER" -gt 0 ]; then
logger -t check-vpn -p user.notice "VPN tunnel to ${peer} restored after restart"
fi
fi
doneConfiguration Examples
Example 1: Basic Backup
# Daily configuration backup at 2:00 AM
set system task-scheduler task daily-backup interval '0 2 * * *'
set system task-scheduler task daily-backup executable path '/config/scripts/backup.sh'
commit
saveScript /config/scripts/backup.sh:
#!/bin/bash
DATE=$(date +%Y%m%d)
/opt/vyatta/sbin/vyatta-save-config.pl /config/backups/config-${DATE}.boot
# Remove old backups (older than 7 days)
find /config/backups -name "config-*.boot" -mtime +7 -delete
logger -t daily-backup "Configuration backup completed"Example 2: Interface Monitoring
# Check the interface state every 5 minutes
set system task-scheduler task interface-monitor interval '*/5 * * * *'
set system task-scheduler task interface-monitor executable path '/config/scripts/interface-monitor.sh'
commit
saveScript /config/scripts/interface-monitor.sh:
#!/bin/bash
INTERFACES=("eth0" "eth1")
ALERT_EMAIL="admin@example.com"
for iface in "${INTERFACES[@]}"; do
STATUS=$(ip link show $iface | grep -c "state UP")
if [ "$STATUS" -eq 0 ]; then
echo "Interface $iface is DOWN on $(hostname)" | \
mail -s "Interface Alert" $ALERT_EMAIL
logger -t interface-monitor -p user.err "Interface $iface is DOWN"
fi
doneExample 3: Periodic DHCP Lease Cleanup
# Weekly cleanup of old DHCP leases
set system task-scheduler task cleanup-dhcp interval '0 3 * * 0'
set system task-scheduler task cleanup-dhcp executable path '/usr/bin/systemctl restart isc-dhcp-server'
commit
saveExample 4: Dynamic DNS Update
# Update DDNS every 30 minutes (if there is no built-in DDNS)
set system task-scheduler task update-ddns interval '*/30 * * * *'
set system task-scheduler task update-ddns executable path '/config/scripts/update-ddns.sh'
commit
saveScript /config/scripts/update-ddns.sh:
#!/bin/bash
DDNS_URL="https://dyndns.example.com/update"
DDNS_TOKEN="your-token-here"
HOSTNAME="router.example.com"
# Get the external IP
CURRENT_IP=$(curl -s ifconfig.me)
# Update through the API
curl -X POST "${DDNS_URL}" \
-H "Authorization: Bearer ${DDNS_TOKEN}" \
-d "hostname=${HOSTNAME}&ip=${CURRENT_IP}"
logger -t update-ddns "DDNS updated with IP ${CURRENT_IP}"Example 5: Monthly Reboot (Maintenance Window)
# Reboot on the first Sunday of the month at 5:00 AM
set system task-scheduler task monthly-reboot interval '0 5 1-7 * 0'
set system task-scheduler task monthly-reboot executable path '/sbin/reboot'
commit
saveExample 6: Traffic Statistics
# Collect interface statistics every hour
set system task-scheduler task traffic-stats interval '0 * * * *'
set system task-scheduler task traffic-stats executable path '/config/scripts/traffic-stats.sh'
commit
saveScript /config/scripts/traffic-stats.sh:
#!/bin/bash
STATS_FILE="/var/log/traffic-stats.log"
DATE=$(date '+%Y-%m-%d %H:%M:%S')
# Get statistics for eth0
RX_BYTES=$(cat /sys/class/net/eth0/statistics/rx_bytes)
TX_BYTES=$(cat /sys/class/net/eth0/statistics/tx_bytes)
# Write to the log
echo "${DATE},eth0,${RX_BYTES},${TX_BYTES}" >> ${STATS_FILE}
# Log to syslog
logger -t traffic-stats "Statistics collected: RX=${RX_BYTES}, TX=${TX_BYTES}"Monitoring and Diagnostics
Viewing Configured Tasks
# Show all tasks
show system task-scheduler
# Show the configuration in command format
show configuration commands | match task-schedulerChecking Cron Jobs
# View active cron jobs
sudo crontab -l
# Cron execution logs
show log | match CRON
grep CRON /var/log/syslogMonitoring Task Execution
# View syslog for scheduler tasks
show log | match task-scheduler
# Last 50 cron entries
show log tail 50 | match CRON
# Real-time monitoring
monitor log | match CRONTesting a Script Manually
# Run the script directly for testing
sudo /config/scripts/backup.sh
# Check execute permissions
ls -l /config/scripts/
# View the script output
sudo bash -x /config/scripts/backup.shChecking the Last Execution
# View file timestamps (for scripts that create files)
ls -lt /config/backups/
# Logs of the last execution
sudo grep "task-name" /var/log/syslog | tail -20Troubleshooting
Problem: The Task Does Not Run
Diagnostics:
# 1. Check the task configuration
show configuration system task-scheduler task <task-name>
# 2. Check cron
sudo crontab -l | grep <task-name>
# 3. Check the cron logs
grep CRON /var/log/syslog | tail -50
# 4. Check the script permissions
ls -l /config/scripts/<script-name>
# 5. Run the script manually
sudo /config/scripts/<script-name>Solution:
# Make the script executable
sudo chmod +x /config/scripts/<script-name>
# Verify the cron expression syntax (it must be in quotes)
set system task-scheduler task <task-name> interval '*/5 * * * *'
# Restart cron (if necessary)
sudo systemctl restart cron
commit
saveProblem: The Script Runs but Does Not Work Correctly
Diagnostics:
# Run with debug output
sudo bash -x /config/scripts/<script-name>
# Redirect the output to a file for analysis
sudo /config/scripts/<script-name> > /tmp/debug.log 2>&1
cat /tmp/debug.log
# Check the environment variables
sudo env | sortSolution:
Add logging to the script:
#!/bin/bash
# Enable debug
set -x
# Log the start
logger -t my-script "Script started"
# Your code here
...
# Log the completion
logger -t my-script "Script completed"
# Redirect stderr to syslog
exec 2> >(logger -t my-script)Problem: The Task Runs Too Often or Too Rarely
Diagnostics:
# Check the cron expression
show configuration system task-scheduler task <task-name> interval
# Test the schedule online
# Use https://crontab.guru to verify the syntaxSolution:
# Examples of adjusting the frequency
# Was: every minute (too often)
# * * * * *
# Changed: every 5 minutes
set system task-scheduler task <task-name> interval '*/5 * * * *'
# Was: every day at 2:00 AM (too rare for a critical task)
# 0 2 * * *
# Changed: every 6 hours
set system task-scheduler task <task-name> interval '0 */6 * * *'
commit
saveProblem: The Task Cannot Find Commands or Files
Cause: Cron runs with a limited PATH and without the full environment.
Solution:
# Set the full PATH at the beginning of the script
#!/bin/bash
# Set PATH
export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
# Explicitly specify full paths to commands
/usr/bin/curl https://example.com
/opt/vyatta/sbin/vyatta-save-config.pl /tmp/config.boot
# For VyOS operational commands
source /opt/vyatta/etc/functions/script-templateProblem: No Output/Logs from the Task
Solution:
Add output redirection to the configuration:
# Modify the script to log all output
#!/bin/bash
# Redirect stdout and stderr to syslog
exec 1> >(logger -t my-task -p user.info)
exec 2> >(logger -t my-task -p user.err)
# Now all output goes to syslog
echo "This will appear in syslog"Or redirect to a file:
set system task-scheduler task <task-name> executable path '/config/scripts/script.sh >> /var/log/task.log 2>&1'Problem: The Task Conflicts with Other Operations
Scenario: A backup task conflicts with configuration changes.
Solution:
Use locking in the script:
#!/bin/bash
LOCKFILE="/var/run/my-task.lock"
# Check whether the lock file exists
if [ -f "$LOCKFILE" ]; then
logger -t my-task "Task already running, exiting"
exit 1
fi
# Create the lock file
touch $LOCKFILE
# Trap to remove the lock file on exit
trap "rm -f $LOCKFILE" EXIT
# Main script logic
...
# The lock file is removed automatically on exitBest Practices
1. Execute Permissions and Shebang
Always add a shebang and make your scripts executable:
#!/bin/bash
# Your script
# Make it executable
sudo chmod +x /config/scripts/script.sh2. Logging
Always log task execution:
#!/bin/bash
logger -t my-task "Task started"
# Your logic
logger -t my-task "Task completed successfully"3. Error Handling
Add error handling:
#!/bin/bash
set -e # Stop on error
# Or an explicit check
if ! command_that_might_fail; then
logger -t my-task -p user.err "Command failed"
exit 1
fi4. Full Paths
Use absolute paths for commands and files:
# Bad
cp config.boot /tmp/
# Good
/bin/cp /config/config.boot /tmp/config-backup.boot5. Testing
Test scripts manually before adding them to the scheduler:
# Run manually
sudo /config/scripts/script.sh
# With debug
sudo bash -x /config/scripts/script.sh6. Documentation
Comment your scripts and tasks:
# Create a task with a descriptive name
set system task-scheduler task daily-config-backup interval '0 2 * * *'
set system task-scheduler task daily-config-backup executable path '/config/scripts/backup.sh'
# In the script
#!/bin/bash
# Description: Daily configuration backup to remote server
# Author: Network Team
# Last modified: 2025-10-147. Execution Monitoring
Set up monitoring for critical tasks:
# Send status to the monitoring system
curl -X POST https://monitoring.example.com/heartbeat/task-name8. Temporary File Cleanup
Remove temporary files after use:
#!/bin/bash
TEMP_FILE="/tmp/temp-$$.txt"
# Trap for cleanup
trap "rm -f $TEMP_FILE" EXIT
# Use the temp file
...9. Security
Do not store passwords in scripts:
# Bad
PASSWORD="secret123"
# Good - use SSH keys or tokens in protected files
API_KEY=$(cat /config/auth/api-key.txt)10. Scheduling and Load
Spread tasks out over time:
# Avoid multiple tasks at the same time
# Bad:
# Backup: 0 2 * * *
# Cleanup: 0 2 * * *
# Report: 0 2 * * *
# Good:
# Backup: 0 2 * * * (2:00 AM)
# Cleanup: 0 3 * * * (3:00 AM)
# Report: 0 4 * * * (4:00 AM)Useful Commands
# Show all tasks
show system task-scheduler
# Configuration in command format
show configuration commands | match task-scheduler
# View the crontab
sudo crontab -l
# Cron logs
show log | match CRON
grep CRON /var/log/syslog
# Run a script manually
sudo /config/scripts/script.sh
# Check permissions
ls -l /config/scripts/
# Test with debug
sudo bash -x /config/scripts/script.sh
# Monitor execution
monitor log | match task-name
# Edit a script
edit /config/scripts/script.sh
# Check bash script syntax
bash -n /config/scripts/script.sh
# Restart cron (if needed)
sudo systemctl restart cron
# Cron status
sudo systemctl status cronIntegration with Other VyOS Features
API Integration
# Periodically call the VyOS REST API
set system task-scheduler task api-health-check interval '*/10 * * * *'
set system task-scheduler task api-health-check executable path '/config/scripts/api-check.sh'Script:
#!/bin/bash
API_KEY="your-api-key"
API_URL="https://localhost/retrieve"
RESPONSE=$(curl -k -X POST "${API_URL}" \
-H "Content-Type: application/json" \
-H "key: ${API_KEY}" \
-d '{"op":"showConfig","path":[]}' \
-w "%{http_code}" -o /dev/null -s)
if [ "$RESPONSE" != "200" ]; then
logger -t api-check -p user.err "API health check failed: HTTP ${RESPONSE}"
else
logger -t api-check "API health check OK"
fiHigh Availability Integration (VRRP)
# Check the VRRP status
set system task-scheduler task vrrp-monitor interval '*/5 * * * *'
set system task-scheduler task vrrp-monitor executable path '/config/scripts/vrrp-monitor.sh'Performance Monitoring Integration
# Collect performance metrics
set system task-scheduler task perf-monitor interval '*/1 * * * *'
set system task-scheduler task perf-monitor executable path '/config/scripts/perf-monitor.sh'Conclusion
The Task Scheduler in VyOS is a powerful tool for automating routine operations and building fault-tolerant infrastructure. Proper use of the task scheduler lets you:
- Automate backup and recovery
- Proactively monitor the state of the system and services
- Perform regular maintenance without manual intervention
- Integrate with external monitoring and management systems
- Reduce the workload on administrators
For production environments, we recommend that you:
- Set up a daily configuration backup
- Monitor critical services and interfaces
- Log the execution of all tasks to syslog
- Test scripts manually before adding them to the scheduler
- Document all automated tasks