BudiBadu Logo
Samplebadu

Bash by Example: Simple Task Scheduler

Bash 5.0+

A lightweight alternative to cron for running sequential tasks without external dependencies, implementing simple task scheduling within scripts, executing commands at specified intervals with sleep, building custom job schedulers, and managing task dependencies without complex cron syntax.

Code

#!/bin/bash

TASKS_FILE="tasks.txt"
LOG_FILE="scheduler.log"

# Create dummy tasks
echo "echo 'Running Task A'; sleep 2" > "$TASKS_FILE"
echo "echo 'Running Task B'; sleep 1" >> "$TASKS_FILE"
echo "ls -la /tmp" >> "$TASKS_FILE"

echo "Starting Scheduler..."

# Read tasks line by line
while IFS= read -r task_cmd; do
    # Skip empty lines or comments
    [[ -z "$task_cmd" || "$task_cmd" =~ ^# ]] && continue
    
    echo "--------------------------------"
    echo "Executing: $task_cmd"
    
    start_time=$(date +%s)
    
    # Execute the command string
    # eval is dangerous with untrusted input, but useful here
    eval "$task_cmd" >> "$LOG_FILE" 2>&1
    exit_code=$?
    
    end_time=$(date +%s)
    duration=$((end_time - start_time))
    
    if [ $exit_code -eq 0 ]; then
        echo "Success (Duration: ${duration}s)"
    else
        echo "Failed (Exit Code: $exit_code)"
    fi
    
done < "$TASKS_FILE"

echo "All tasks processed. Check $LOG_FILE for details."
rm "$TASKS_FILE"

Explanation

While cron is the standard for time-based scheduling (e.g., "run at 5 AM"), sometimes you need a simple "batch processor" that runs a list of commands sequentially, one after another, and logs the results. This is common in deployment pipelines, data migration scripts, or nightly maintenance routines where Step B must strictly follow Step A.

This script reads a text file containing commands line-by-line. It executes each command, captures its output to a log file, measures how long it took, and checks if it succeeded. This provides a structured way to run a "playlist" of maintenance tasks without writing a massive monolithic script.

The use of eval allows us to execute strings read from a file as if they were typed in the shell (handling pipes, redirects, etc.). However, warning: never use eval on input you don't fully trust, as it can execute arbitrary code.

Code Breakdown

14
while IFS= read -r ... is the canonical, safe way to read a file line-by-line in Bash. It preserves whitespace and prevents backslashes from being interpreted as escape characters.
25
eval "$task_cmd". If the line is ls | grep foo, simple execution won't work because the pipe is just text. eval parses the line again, recognizing the pipe syntax.