Scheduler
Scheduler
Section titled “Scheduler”The RouterOS Scheduler allows you to automate tasks by running scripts or commands at specific times, after a set interval, or immediately on router startup. Common uses include automated backups, log rotation, periodic reboots, interface monitoring, and any other maintenance work that benefits from hands-free execution.
Overview
Section titled “Overview”The scheduler integrates with the /system script subsystem. Each scheduler entry specifies:
- When to run — a specific date/time, an interval, or at startup
- What to run — a named script from
/system script, or an inline command - With what permissions — the policy flags the task executes under
Accurate system time is required for time-based triggers. See Clock and NTP for time configuration.
Sub-menu
Section titled “Sub-menu”/system schedulerProperties
Section titled “Properties”Configurable Properties
Section titled “Configurable Properties”| Property | Type / Values | Description |
|---|---|---|
name | string | Unique name for the scheduler entry |
start-date | date (mmm/DD/YYYY) | The first date the task is eligible to run. Defaults to the current date |
start-time | time (HH:MM:SS) or startup | Time of day to first run, or startup to trigger approximately 3 seconds after the router boots |
interval | duration (w/d/h/m/s) | How often to repeat. Setting interval=0 runs the task exactly once |
on-event | string | A /system script name, or an inline RouterOS command to execute |
policy | flag list | Permissions granted to the task. Possible flags: read, write, policy, test, password, sniff, sensitive, romon, dude, api |
comment | string | Administrative note — visible in the scheduler list |
disabled | yes / no | When yes, the entry is skipped entirely |
Read-only Properties
Section titled “Read-only Properties”| Property | Description |
|---|---|
run-count | Number of times this task has executed since the last reboot |
next-run | Date and time of the next scheduled execution |
Interval Format
Section titled “Interval Format”Durations combine weeks (w), days (d), hours (h), minutes (m), and seconds (s):
| Example | Meaning |
|---|---|
interval=1d | Every 24 hours |
interval=12h | Every 12 hours |
interval=1w | Every 7 days |
interval=30m | Every 30 minutes |
interval=1d12h | Every 36 hours |
interval=0 | Run once, do not repeat |
start-time=startup
Section titled “start-time=startup”When start-time=startup is set, the task fires approximately 3 seconds after the router console starts. This is useful for initialization tasks that must run on every boot regardless of the time of day.
If interval is also set alongside startup, the task fires at startup and then continues repeating on that interval.
Configuration
Section titled “Configuration”Viewing Scheduled Tasks
Section titled “Viewing Scheduled Tasks”/system scheduler printExample output:
Flags: X - disabled # NAME START-DATE START-TIME INTERVAL ON-EVENT 0 nightly-backup jan/01/1970 03:00:00 1d run-backup 1 startup-check jan/01/1970 startup 0 check-interfacesAdding a Scheduled Task
Section titled “Adding a Scheduled Task”/system scheduler add \ name=nightly-backup \ start-date=jan/01/1970 \ start-time=03:00:00 \ interval=1d \ on-event=run-backup \ policy=read,write,policy,test,password,sensitive \ comment="Daily backup at 3 AM"Editing an Existing Task
Section titled “Editing an Existing Task”/system scheduler set nightly-backup start-time=02:00:00Disabling and Enabling a Task
Section titled “Disabling and Enabling a Task”# Disable/system scheduler disable nightly-backup
# Enable/system scheduler enable nightly-backupRemoving a Task
Section titled “Removing a Task”/system scheduler remove nightly-backupRunning a Task Manually
Section titled “Running a Task Manually”RouterOS has no run command under /system scheduler. To trigger a task immediately, run the underlying script directly:
/system script run nightly-backupExamples
Section titled “Examples”Daily Automated Backup
Section titled “Daily Automated Backup”Creates a script that exports the configuration to a file, then schedules it to run every day at 02:00:
# Create the backup script/system script add name=run-backup policy=read,write,policy,test,password,sensitive \ source="/export file=backup-[/system identity get name]"
# Schedule it to run daily at 02:00/system scheduler add \ name=nightly-backup \ start-time=02:00:00 \ interval=1d \ on-event=run-backup \ policy=read,write,policy,test,password,sensitive \ comment="Daily config backup"Startup Initialization Task
Section titled “Startup Initialization Task”Run a script once every time the router boots to restore dynamic state or send a notification:
/system script add name=on-boot \ policy=read,write,test \ source="/log info \"Router has started\""
/system scheduler add \ name=boot-init \ start-time=startup \ interval=0 \ on-event=on-boot \ policy=read,write,test \ comment="Run once at every boot"Periodic Reboot (Weekly Maintenance)
Section titled “Periodic Reboot (Weekly Maintenance)”Schedule a weekly reboot during a maintenance window:
/system scheduler add \ name=weekly-reboot \ start-date=jan/01/1970 \ start-time=04:00:00 \ interval=1w \ on-event="/system reboot" \ policy=read,write,policy,reboot \ comment="Weekly maintenance reboot Sunday 4 AM"One-Time Scheduled Task
Section titled “One-Time Scheduled Task”Run a command exactly once at a future time (useful for planned changes):
/system scheduler add \ name=one-time-change \ start-date=mar/25/2026 \ start-time=22:00:00 \ interval=0 \ on-event="/interface disable ether2" \ policy=read,write \ comment="Disable ether2 at 10 PM March 25"This entry runs once and does not repeat. After execution, run-count shows 1 and next-run becomes empty.
Inline Command vs. Named Script
Section titled “Inline Command vs. Named Script”on-event accepts either a /system script name or an inline command:
# Using a named script (preferred for multi-line logic)/system scheduler add name=use-script on-event=my-script-name \ start-time=06:00:00 interval=1d policy=read,write
# Using inline command (fine for simple one-liners)/system scheduler add name=log-heartbeat \ on-event="/log info \"heartbeat\"" \ start-time=startup interval=5m policy=readFor anything beyond a single command, define the logic in /system script and reference it by name.
Passing Arguments to Scripts
Section titled “Passing Arguments to Scripts”The scheduler has no native argument-passing field. The two common patterns are:
Pattern 1 — Global variable set inline
Set a global before calling the named script. The script reads the global at runtime:
# Script that reads a global argument/system script add name=rotate-backup \ policy=read,write,policy,test,sensitive \ source={ :global keepDays :if ([:len $keepDays] = 0) do={ :set keepDays 7 } :log info ("Rotating backups, keeping $keepDays days") # ... rotation logic using $keepDays ... }
# Scheduler entry sets the global, then calls the script/system scheduler add \ name=rotate-backup-14d \ start-time=04:00:00 \ interval=1d \ on-event=":global keepDays 14; /system script run rotate-backup" \ policy=read,write,policy,test,sensitive \ comment="Rotate backups, keep 14 days"Pattern 2 — Fully inline logic
For simple one-off parameterisation, embed the logic directly in on-event:
/system scheduler add \ name=disable-ether2 \ start-date=mar/25/2026 \ start-time=22:00:00 \ interval=0 \ on-event="/interface disable ether2" \ policy=read,write \ comment="One-time: disable ether2 at 22:00 on Mar 25"Automated Backup with FTP/SFTP Upload
Section titled “Automated Backup with FTP/SFTP Upload”Creates a timestamped binary backup and exports the configuration, then uploads both to a remote server. The script requires ftp, sensitive, and password policies in addition to read and write.
# Create the upload script/system script add name=backup-upload \ policy=read,write,policy,test,password,sensitive,ftp \ source={ :local id [/system identity get name] :local d [/system clock get date] :local base ($id . "-" . [:pick $d 7 11] . [:pick $d 4 6] . [:pick $d 0 3]) :local backupFile ($base . ".backup") :local exportFile ($base . ".rsc")
# Create local backup files :do { /system backup save name=$base encryption=aes-sha256 /export file=$base } on-error={ :log error "BACKUP: failed to create local files" :error "backup-failed" }
# Wait for files to be written :delay 3s
# Upload binary backup :do { /tool fetch mode=sftp address=203.0.113.10 port=22 \ src-path=$backupFile upload=yes \ user=backupuser password="StrongPassword" \ dst-path=("/backups/" . $backupFile) :log info ("BACKUP: uploaded " . $backupFile) } on-error={ :log error ("BACKUP: upload failed for " . $backupFile) }
# Upload text export :do { /tool fetch mode=sftp address=203.0.113.10 port=22 \ src-path=$exportFile upload=yes \ user=backupuser password="StrongPassword" \ dst-path=("/backups/" . $exportFile) :log info ("BACKUP: uploaded " . $exportFile) } on-error={ :log error ("BACKUP: upload failed for " . $exportFile) } }
# Schedule daily at 02:30/system scheduler add \ name=daily-backup-upload \ start-time=02:30:00 \ interval=1d \ on-event=backup-upload \ policy=read,write,policy,test,password,sensitive,ftp \ comment="Daily backup + SFTP upload"For FTP instead of SFTP, change mode=sftp port=22 to mode=ftp port=21.
Interface Toggle (Bounce)
Section titled “Interface Toggle (Bounce)”Disable and re-enable an interface — useful for resetting a link without a full reboot:
/system script add name=bounce-wan \ policy=read,write \ source={ :local iface "ether1" :log info ("Bouncing " . $iface) /interface disable $iface :delay 10s /interface enable $iface :log info ($iface . " re-enabled") }
# Schedule a weekly bounce during maintenance window/system scheduler add \ name=weekly-wan-bounce \ start-date=jan/01/1970 \ start-time=04:00:00 \ interval=1w \ on-event=bounce-wan \ policy=read,write \ comment="Weekly WAN interface bounce"To trigger the bounce immediately for testing:
/system script run bounce-wanPermissions and Policy
Section titled “Permissions and Policy”Each scheduler entry has its own policy flag set. When a scheduled task calls a named script, RouterOS checks that the intersection of the scheduler policy and the script policy is sufficient to perform the operations in the script.
If a script requires write permission but the scheduler entry’s policy does not include write, the task will fail with a permissions error.
dont-require-permissions
Section titled “dont-require-permissions”For scripts that need to run from the scheduler without strict policy matching, set dont-require-permissions=yes on the script:
/system script set my-script dont-require-permissions=yesUse this only for trusted, internally maintained scripts. It bypasses all permission checks for that script regardless of which facility calls it.
Troubleshooting
Section titled “Troubleshooting”Task Not Running
Section titled “Task Not Running”-
Check the task is enabled:
/system scheduler printDisabled entries are flagged with
X. -
Verify
next-runis populated and in the future:/system scheduler print detail -
Confirm system time is correct — tasks will not trigger if the clock is wrong:
/system clock print
Task Runs but Produces No Effect
Section titled “Task Runs but Produces No Effect”-
Check the system log for script errors:
/log print where topics~"script" -
Confirm the scheduler policy includes the permissions the script needs (e.g.,
writefor configuration changes,testfor ping/traceroute). -
Try running the underlying script manually to reproduce the error interactively:
/system script run task-name
Overlapping Executions
Section titled “Overlapping Executions”If a task takes longer than its interval, RouterOS will not start a second instance — the current run continues and the next trigger is skipped. To avoid missed runs, set interval to be safely longer than the maximum expected execution time.
Permission Denied Errors
Section titled “Permission Denied Errors”If the log shows permission denied for a scheduled script:
- Check the policy flags on both the scheduler entry and the script.
- Ensure required flags (e.g.,
write,policy,sensitive) are present on the scheduler entry. - Consider
dont-require-permissions=yeson the script if the execution context cannot hold the required flags.