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

CharacterDescriptionExample
*Any value* * * * * - every minute
,List of values0,15,30,45 * * * * - at 0, 15, 30, and 45 minutes of every hour
-Range of values0 9-17 * * * - every hour from 9:00 to 17:00
/Step (interval)*/5 * * * * - every 5 minutes
*/nEvery n units0 */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 * * 0

Basic 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
save

Running 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
save

Running 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
save

Tasks 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
save

Advanced 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
save

Contents 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.sh

Monitoring 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
save

Contents 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
done

Cleaning 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
save

Contents 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
save

Contents 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
save

Contents 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
save

Contents 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
done

Configuration 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
save

Script /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
save

Script /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
done

Example 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
save

Example 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
save

Script /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
save

Example 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
save

Script /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-scheduler

Checking Cron Jobs

# View active cron jobs
sudo crontab -l

# Cron execution logs
show log | match CRON
grep CRON /var/log/syslog

Monitoring 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 CRON

Testing 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.sh

Checking 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 -20

Troubleshooting

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
save

Problem: 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 | sort

Solution:

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 syntax

Solution:

# 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
save

Problem: 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-template

Problem: 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 exit

Best 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.sh

2. 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
fi

4. Full Paths

Use absolute paths for commands and files:

# Bad
cp config.boot /tmp/

# Good
/bin/cp /config/config.boot /tmp/config-backup.boot

5. 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.sh

6. 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-14

7. Execution Monitoring

Set up monitoring for critical tasks:

# Send status to the monitoring system
curl -X POST https://monitoring.example.com/heartbeat/task-name

8. 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 cron

Integration 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"
fi

High 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
Reviewed by OpenNix LLC · Last updated on