Whether you're running Windows Task Scheduler or Linux cron, scheduled tasks need monitoring. This guide covers both platforms with practical examples for reliable alerting.
Linux: Cron Job Monitoring
Basic Cron Monitoring
Add a heartbeat ping to your cron entry:
# Before
0 2 * * * /home/user/backup.sh
# After
0 2 * * * /home/user/backup.sh && curl -fsS https://wizstatus.com/ping/TOKEN
Wrapper Script Approach
Create a reusable wrapper:
#!/bin/bash
# /usr/local/bin/cron-monitor
PING_URL="$1"
shift
# Run the command
"$@"
EXIT_CODE=$?
# Ping on success
if [ $EXIT_CODE -eq 0 ]; then
curl -fsS --retry 3 "$PING_URL"
fi
exit $EXIT_CODE
Usage:
0 2 * * * /usr/local/bin/cron-monitor https://wizstatus.com/ping/TOKEN /home/user/backup.sh
Systemd Timers (Modern Linux)
For systemd-based systems, use timer units:
# /etc/systemd/system/backup.service
[Unit]
Description=Daily Backup
[Service]
Type=oneshot
ExecStart=/home/user/backup.sh
ExecStartPost=/usr/bin/curl -fsS https://wizstatus.com/ping/TOKEN
# /etc/systemd/system/backup.timer
[Unit]
Description=Run backup daily
[Timer]
OnCalendar=*-*-* 02:00:00
Persistent=true
[Install]
WantedBy=timers.target
Enable with:
systemctl enable --now backup.timer
Windows: Task Scheduler Monitoring
Method 1: PowerShell Wrapper
Create a PowerShell wrapper script:
# C:\Scripts\Task-Monitor.ps1
param(
[string]$PingUrl,
[string]$ScriptPath,
[string[]]$Arguments
)
try {
# Run the actual script
if ($Arguments) {
& $ScriptPath @Arguments
} else {
& $ScriptPath
}
# Ping on success
if ($LASTEXITCODE -eq 0 -or $LASTEXITCODE -eq $null) {
Invoke-WebRequest -Uri $PingUrl -Method GET -UseBasicParsing | Out-Null
}
}
catch {
Write-Error $_.Exception.Message
exit 1
}
In Task Scheduler, configure:
- Program:
powershell.exe - Arguments:
-ExecutionPolicy Bypass -File "C:\Scripts\Task-Monitor.ps1" -PingUrl "https://wizstatus.com/ping/TOKEN" -ScriptPath "C:\Scripts\backup.ps1"
Method 2: Batch File Wrapper
@echo off
REM C:\Scripts\task-wrapper.bat
SET PING_URL=%1
SHIFT
SET COMMAND=%*
REM Run the command
CALL %COMMAND%
REM Check exit code and ping
IF %ERRORLEVEL% EQU 0 (
curl -s "%PING_URL%"
)
Method 3: Post-Action in Task Scheduler
Add a second action to your task:
- Open Task Scheduler
- Edit your task
- Go to Actions tab
- Add New Action:
- Program:
curl.exe - Arguments:
-s https://wizstatus.com/ping/TOKEN
- Program:
Note: This runs regardless of first action's result. Use wrapper for conditional pinging.
Installing curl on Windows
Modern Windows 10/11 includes curl. For older systems:
# Using winget
winget install curl
# Or use PowerShell's Invoke-WebRequest
Invoke-WebRequest -Uri $URL -Method GET
Cross-Platform Solutions
Python Script
Works on both Windows and Linux:
#!/usr/bin/env python3
# monitor-task.py
import subprocess
import sys
import requests
def main():
ping_url = sys.argv[1]
command = sys.argv[2:]
try:
result = subprocess.run(command, check=True)
if result.returncode == 0:
requests.get(ping_url, timeout=30)
except subprocess.CalledProcessError as e:
print(f"Command failed: {e}")
sys.exit(1)
except requests.RequestException as e:
print(f"Ping failed: {e}")
if __name__ == "__main__":
main()
Usage:
# Linux
python3 monitor-task.py https://wizstatus.com/ping/TOKEN /path/to/script.sh
# Windows
python monitor-task.py https://wizstatus.com/ping/TOKEN C:\Scripts\backup.bat
Configuring Heartbeat Monitors
Linux Cron
For a daily job at 2 AM:
- Schedule: Daily at 02:00
- Grace period: 60 minutes (for job duration + buffer)
- Timezone: Match server timezone
Windows Task Scheduler
For a weekly backup on Sunday at 3 AM:
- Schedule: Weekly on Sunday at 03:00
- Grace period: 120 minutes
- Timezone: Match server timezone
Best Practices
Use Absolute Paths
Cron and Task Scheduler may have different PATH:
# Bad
0 2 * * * backup.sh && curl https://ping-url
# Good
0 2 * * * /home/user/backup.sh && /usr/bin/curl https://ping-url
Log Everything
# Linux
0 2 * * * /home/user/backup.sh >> /var/log/backup.log 2>&1 && curl $PING_URL
# Windows
Start-Transcript -Path "C:\Logs\backup.log" -Append
Handle Failures Gracefully
#!/bin/bash
set -e # Exit on any error
do_backup
do_verification
do_cleanup
# Only reached if all succeeded
curl $PING_URL
Test After Configuration
Run tasks manually to verify:
# Linux
/home/user/backup.sh && curl $PING_URL
# Windows (Run as the service account)
runas /user:SYSTEM "C:\Scripts\backup.bat"
Troubleshooting
Linux: Job Not Running
Check:
# Is cron running?
systemctl status cron
# Check cron logs
grep CRON /var/log/syslog
# Verify crontab
crontab -l
Windows: Task Not Running
Check:
- Task history in Task Scheduler
- Event Viewer > Windows Logs > System
- Run "As administrator" if needed
- Check "Run whether user is logged on or not"
Ping Not Working
Verify network access:
# Linux
curl -v https://wizstatus.com/ping/TOKEN
# Windows PowerShell
Invoke-WebRequest -Uri "https://wizstatus.com/ping/TOKEN" -Verbose
Platform Comparison
| Feature | Linux Cron | Windows Task Scheduler |
|---|---|---|
| Config format | Crontab text | GUI + XML |
| Timezone | System default | Configurable per task |
| Missed runs | Not executed | Can be configured |
| Dependencies | Manual | Action dependencies |
| Event triggers | Via systemd | Native support |
| Exit code | Available | Available |