DEV Community

Haripriya Veluchamy
Haripriya Veluchamy

Posted on

Building a User-Friendly Task Scheduler in Bash

Working with cron jobs on Linux systems can be intimidating for newcomers and tedious even for experienced users. Today, I'm sharing a simple yet powerful Bash Task Scheduler that provides a clean interface for managing scheduled tasks without needing to remember crontab's syntax.

The Problem

If you've ever tried to schedule recurring tasks on a Unix-based system, you've likely encountered crontab. While powerful, the crontab syntax isn't particularly intuitive:

# ┌───────────── minute (0 - 59)
# │ ┌───────────── hour (0 - 23)
# │ │ ┌───────────── day of the month (1 - 31)
# │ │ │ ┌───────────── month (1 - 12)
# │ │ │ │ ┌───────────── day of the week (0 - 6) (Sunday to Saturday)
# │ │ │ │ │
# │ │ │ │ │
# * * * * * command to execute
Enter fullscreen mode Exit fullscreen mode

For someone who doesn't work with cron regularly, this can lead to errors and frustration. Even for regular users, it's easy to make a mistake when directly editing the crontab file.

The Solution

I created a Bash script that wraps around crontab to provide a user-friendly interface for scheduling tasks. The script offers:

  1. A clean menu-driven interface
  2. Simple options for common scheduling patterns
  3. The ability to view, add, and remove tasks easily
  4. No external dependencies beyond standard Unix utilities

Let's walk through how it works.

How the Script Works

Core Functionality

The script is structured around four main functions:

  1. display_header - Creates a consistent UI experience
  2. display_tasks - Lists all currently scheduled tasks
  3. add_task - Guides users through adding a new task
  4. remove_task - Allows users to remove existing tasks

These functions are tied together by a simple menu loop that provides the main interface.

Task Display

When displaying tasks, the script filters out comments from the crontab output and adds line numbers for easier reference:

# Check if crontab exists
if crontab -l 2>/dev/null | grep -v "^#" | grep -q .; then
    # Display tasks with line numbers
    crontab -l | grep -v "^#" | grep . | nl -w2 -s') '
else
    echo "No tasks currently scheduled."
fi
Enter fullscreen mode Exit fullscreen mode

This gives users a clear view of their scheduled tasks without the clutter of comments or empty lines.

Adding Tasks

The task creation process is where this script really shines. Instead of requiring users to construct cron expressions manually, it offers pre-configured options:

echo "Please select the schedule type:"
echo "1) Hourly"
echo "2) Daily"
echo "3) Weekly"
echo "4) Custom (Advanced)"
Enter fullscreen mode Exit fullscreen mode

For example, if a user wants a task to run daily, the script will automatically generate a cron expression like 34 12 * * * (running at 12:34 PM every day).

For those who know crontab syntax, there's still a custom option to enter a specific cron expression.

Task Management

When it comes to removing tasks, the script displays each task with a number, allowing users to simply enter the number of the task they want to remove:

# Display tasks with line numbers
crontab -l | grep -v "^#" | grep . | nl -w2 -s') '

echo
read -p "Enter the number of the task to remove (0 to cancel): " task_number
Enter fullscreen mode Exit fullscreen mode

The script then handles the removal by creating a temporary crontab file without the selected task and applying it.

The Code

Here's the full script for the Bash Task Scheduler:

#!/bin/bash

# Task Scheduler using Bash
# This script allows for managing scheduled tasks using crontab

# Function to display header
display_header() {
    clear
    echo "====================================="
    echo "        BASH TASK SCHEDULER          "
    echo "====================================="
    echo
}

# Function to display all scheduled tasks
display_tasks() {
    display_header
    echo "CURRENTLY SCHEDULED TASKS:"
    echo "====================================="

    # Check if crontab exists
    if crontab -l 2>/dev/null | grep -v "^#" | grep -q .; then
        # Display tasks with line numbers
        crontab -l | grep -v "^#" | grep . | nl -w2 -s') '
    else
        echo "No tasks currently scheduled."
    fi

    echo
    echo "Press Enter to continue..."
    read -r
}

# Function to add a new task
add_task() {
    display_header
    echo "ADD NEW SCHEDULED TASK"
    echo "====================================="
    echo
    echo "Please select the schedule type:"
    echo "1) Hourly"
    echo "2) Daily"
    echo "3) Weekly"
    echo "4) Custom (Advanced)"
    echo "5) Return to main menu"
    echo
    read -p "Enter your choice (1-5): " schedule_type

    case $schedule_type in
        1) # Hourly
            minute=$(( RANDOM % 60 ))
            cron_time="$minute * * * *"
            timing_desc="Hourly at $minute minutes past the hour"
            ;;
        2) # Daily
            minute=$(( RANDOM % 60 ))
            hour=$(( RANDOM % 24 ))
            cron_time="$minute $hour * * *"
            timing_desc="Daily at $hour:$minute"
            ;;
        3) # Weekly
            minute=$(( RANDOM % 60 ))
            hour=$(( RANDOM % 24 ))
            day_of_week=$(( RANDOM % 7 ))
            day_names=("Sunday" "Monday" "Tuesday" "Wednesday" "Thursday" "Friday" "Saturday")
            cron_time="$minute $hour * * $day_of_week"
            timing_desc="Weekly on ${day_names[$day_of_week]} at $hour:$minute"
            ;;
        4) # Custom
            echo
            read -p "Enter cron expression (e.g., '30 2 * * 1' for Monday at 2:30 AM): " cron_time
            timing_desc="Custom schedule: $cron_time"
            ;;
        5) # Return to main menu
            return
            ;;
        *)
            echo "Invalid selection. Please try again."
            sleep 2
            add_task
            return
            ;;
    esac

    # Get the command to execute
    echo
    echo "Schedule: $timing_desc"
    echo
    read -p "Enter the command to execute: " task_command

    if [ -z "$task_command" ]; then
        echo "Command cannot be empty. Task not added."
        sleep 2
        return
    fi

    # Add task to crontab
    (crontab -l 2>/dev/null; echo "$cron_time $task_command # Scheduled via Task Scheduler") | crontab -

    echo
    echo "Task added successfully!"
    echo "Schedule: $timing_desc"
    echo "Command: $task_command"
    echo
    echo "Press Enter to continue..."
    read -r
}

# Function to remove a task
remove_task() {
    display_header
    echo "REMOVE SCHEDULED TASK"
    echo "====================================="
    echo

    # Check if crontab exists
    if ! crontab -l 2>/dev/null | grep -v "^#" | grep -q .; then
        echo "No tasks currently scheduled."
        echo
        echo "Press Enter to continue..."
        read -r
        return
    fi

    # Display tasks with line numbers
    crontab -l | grep -v "^#" | grep . | nl -w2 -s') '

    echo
    read -p "Enter the number of the task to remove (0 to cancel): " task_number

    if [ "$task_number" -eq 0 ]; then
        return
    fi

    # Get the total number of tasks
    task_count=$(crontab -l | grep -v "^#" | grep . | wc -l)

    if [ "$task_number" -gt 0 ] && [ "$task_number" -le "$task_count" ]; then
        # Create a temporary file with all tasks except the one to be removed
        crontab -l | grep -v "^#" | grep . | awk "NR != $task_number" > /tmp/crontab.tmp

        # Update crontab with the modified content
        crontab /tmp/crontab.tmp
        rm /tmp/crontab.tmp

        echo
        echo "Task removed successfully!"
    else
        echo
        echo "Invalid task number. No tasks were removed."
    fi

    echo
    echo "Press Enter to continue..."
    read -r
}

# Main menu loop
while true; do
    display_header
    echo "MAIN MENU"
    echo "====================================="
    echo "1) Display scheduled tasks"
    echo "2) Add a new task"
    echo "3) Remove a task"
    echo "4) Exit"
    echo
    read -p "Enter your choice (1-4): " choice

    case $choice in
        1) display_tasks ;;
        2) add_task ;;
        3) remove_task ;;
        4) 
            echo "Exiting Task Scheduler. Goodbye!"
            exit 0 
            ;;
        *)
            echo "Invalid selection. Please try again."
            sleep 1
            ;;
    esac
done
Enter fullscreen mode Exit fullscreen mode

Key Technical Insights

Random Scheduling

One interesting aspect of the script is how it handles timing. Rather than asking users to specify exact times for recurring tasks (which can be tedious), it uses Bash's RANDOM function to select times:

minute=$(( RANDOM % 60 ))
hour=$(( RANDOM % 24 ))
day_of_week=$(( RANDOM % 7 ))
Enter fullscreen mode Exit fullscreen mode

This is particularly useful for tasks that need to run regularly but don't require specific timing. It also helps distribute system load by avoiding having all tasks run at common times like the top of the hour.

Temporary Files

The task removal process uses a temporary file to modify the crontab:

crontab -l | grep -v "^#" | grep . | awk "NR != $task_number" > /tmp/crontab.tmp
crontab /tmp/crontab.tmp
rm /tmp/crontab.tmp
Enter fullscreen mode Exit fullscreen mode

This approach allows us to manipulate the crontab content safely before applying changes.

Potential Improvements

While this script works well for basic task scheduling, there are several enhancements that could make it even better:

  1. Better time selection - Allow users to specify exact times rather than relying on random values
  2. Environment variable support - Add functionality to set environment variables for tasks
  3. Output redirection - Make it easy to redirect task output to logs
  4. Task groups - Add the ability to group related tasks and manage them together
  5. Backup and restore - Add options to back up the current crontab before making changes

Conclusion

The Bash Task Scheduler demonstrates how a relatively simple script can significantly improve user experience for a common administrative task. By providing a clean interface for crontab management, it makes task scheduling accessible to users of all skill levels.

Refer t his repo for full setup https://github.com/Harivelu0/shellscript-projects/tree/main/Task_scheduler

What other common command-line tasks would benefit from a more user-friendly interface? Let me know in the comments!

Top comments (0)