How to Set Timeout for Cron Jobs in Ubuntu Linux to Prevent Hanging Processes


3 views

We've all been there - you set up a cron job to run periodically, only to discover later that some instances are hanging indefinitely. Network timeouts, unresponsive external services, or software bugs can leave these processes running forever, consuming system resources.

Ubuntu's default cron (based on Vixie cron) doesn't natively support timeout functionality. While reliable for scheduling, it lacks built-in mechanisms to terminate long-running jobs. This becomes problematic when tasks encounter unexpected delays.

1. Using the timeout Command

The simplest approach is wrapping your command with GNU timeout:

* * * * * /usr/bin/timeout 300 /path/to/your/script.sh

This will kill the process after 300 seconds (5 minutes). The timeout command is part of coreutils and available on all Ubuntu systems.

2. Advanced Timeout with Notifications

For more control, combine timeout with logging and alerting:

* * * * * /usr/bin/timeout 300 /path/to/script.sh > /var/log/script.log 2>&1 || echo "Script timed out" | mail -s "Cron Timeout Alert" admin@example.com

3. Implementing Timeout in Script Itself

For scripts where you need cleanup before timeout, implement it internally:

#!/bin/bash

TIMEOUT=300
START_TIME=$(date +%s)

# Main script logic here
while :; do
    # Your regular processing
    CURRENT_TIME=$(date +%s)
    ELAPSED=$((CURRENT_TIME - START_TIME))
    
    if [ $ELAPSED -gt $TIMEOUT ]; then
        echo "Timeout reached" >&2
        # Add any cleanup here
        exit 1
    fi
done

Systemd timers: For newer systems, consider systemd timers which have built-in timeout controls:

[Service]
ExecStart=/path/to/script.sh
TimeoutStopSec=300

Supervisor: Process managers like supervisor can monitor and kill long-running jobs.

Consider these factors when setting your timeout:

  • Normal execution time of your job
  • Network dependencies and their timeouts
  • Consequences of interrupting the process
  • System resource constraints

Always implement proper logging to track timeout occurrences:

* * * * * /usr/bin/timeout 300 /path/to/script.sh >> /var/log/cron-timeouts.log 2>&1

Regularly review these logs to adjust your timeout values or fix underlying issues causing timeouts.


We've all been there - a cron job gets stuck due to network issues, infinite loops, or unresponsive external services. These orphaned processes can accumulate over time, consuming system resources indefinitely. Unlike modern job schedulers, traditional cron implementations like Vixie cron (the default on Ubuntu) don't include built-in timeout functionality.

Here are three reliable approaches to enforce timeouts:

1. Using the timeout Command

The simplest method uses GNU coreutils' timeout command:


# Basic syntax
* * * * * /usr/bin/timeout 300 /path/to/your/script.sh

# With killing after timeout
* * * * * /usr/bin/timeout -k 30 300 /path/to/your/script.sh

2. Implementing Timeout in Script

For more control, implement timeout logic directly in your script:


#!/bin/bash

TIMEOUT=300
START_TIME=$(date +%s)

# Main execution in background
your_long_running_process &

# Timeout monitoring
while true; do
    if ! ps -p $! >/dev/null; then
        echo "Process completed successfully"
        exit 0
    fi
    
    CURRENT_TIME=$(date +%s)
    if (( CURRENT_TIME - START_TIME > TIMEOUT )); then
        echo "Timeout reached - killing process"
        kill -9 $!
        exit 1
    fi
    
    sleep 5
done

3. Using Systemd for Advanced Control

For Ubuntu systems with systemd, consider using timer units instead of cron:


# Example systemd service unit
[Unit]
Description=My Timed Job

[Service]
Type=simple
ExecStart=/path/to/your/script.sh
TimeoutStopSec=30
TimeoutStartSec=300

# Corresponding timer unit
[Unit]
Description=Run my job hourly

[Timer]
OnCalendar=hourly
Unit=myjob.service

[Install]
WantedBy=timers.target

When implementing timeouts, consider these scenarios:

  • Child processes that might get orphaned
  • Cleanup operations that need to run after timeout
  • Logging timeout events for monitoring

For comprehensive process tree cleanup, use this enhanced timeout command:


* * * * * /usr/bin/timeout --foreground 300 /path/to/your/script.sh

Implement logging to track timeout occurrences:


#!/bin/bash

exec > >(tee -a /var/log/cron_timeouts.log) 2>&1

TIMEOUT=300
/timeout $TIMEOUT /path/to/your/script.sh

if [ $? -eq 124 ]; then
    echo "$(date) - Job timed out after $TIMEOUT seconds" >> /var/log/cron_timeouts.log
    # Add alerting logic here (email, Slack, etc.)
fi