# Module 5

## Automation and Essential Administrative Tasks

### 🎯 Learning Objectives

After completing this module, you will be able to:

- Schedule automated tasks using cron and crontab
- Create basic shell scripts for administrative tasks
- Implement system maintenance procedures
- Execute routine administrative workflows efficiently

Click Next → to begin.

## Introduction to Linux Automation

## Why Automation Matters in Linux Administration

Automation transforms repetitive administrative tasks into reliable, consistent processes that run without human intervention. For Linux administrators, automation is essential for managing systems at scale, reducing errors, and freeing time for strategic work.

Consider the daily responsibilities of a system administrator: checking disk space, rotating logs, backing up critical files, updating security patches, and monitoring system health. Performing these tasks manually on even a handful of servers quickly becomes overwhelming. Automation solves this challenge.

## The Linux Automation Ecosystem

Linux provides powerful native tools for automation:

- Cron daemon: The time-based job scheduler that executes commands at specified intervals
- Shell scripts: Custom programs written in bash or other shells that automate complex workflows
- System utilities: Tools like `rsync`, `tar`, and `find` that perform specific administrative functions

These tools work together seamlessly. You might write a shell script that backs up databases, then use cron to run that script every night at midnight. The script handles the logic; cron handles the scheduling.

## Automation Philosophy

Effective automation follows key principles:

- Start simple: Automate one task completely before moving to the next
- Test thoroughly: Always verify scripts work correctly before scheduling them
- Log everything: Maintain records of automated task execution and results
- Handle errors gracefully: Scripts should detect problems and alert administrators
- Document clearly: Future administrators (including yourself) need to understand what automated tasks do

Automation isn't about eliminating the administrator's role—it's about elevating it. By automating routine tasks, you create time for problem-solving, optimization, and innovation.

Split-screen illustration showing manual repetitive work on left (administrator at multiple terminals looking overwhelmed) versus automated workflow on right (administrator monitoring dashboard while automated processes run smoothly in background)

#### 💡 Key Takeaways

- Automation reduces manual errors and saves administrator time
- Linux provides native tools: cron for scheduling, bash for scripting
- Effective automation requires testing, logging, and clear documentation
- Start with simple tasks and build complexity gradually

## Understanding the Cron System

## The Cron Daemon

The cron daemon (`crond`) is a background service that runs continuously on Linux systems, checking every minute whether any scheduled jobs need to execute. It's one of the oldest and most reliable automation tools in Unix-like systems.

When the system boots, cron starts automatically and reads configuration files that define scheduled tasks. It then waits patiently, executing commands at precisely the right time—whether that's every minute, once a week, or on the first day of every month.

## Crontab: Your Personal Schedule

Each user on a Linux system can maintain their own crontab (cron table)—a file listing scheduled jobs. You edit your crontab with the command:

    crontab -e

This opens your personal crontab in the default text editor. System administrators can also edit other users' crontabs:

    sudo crontab -u username -e

To view your current crontab without editing:

    crontab -l

## Cron Expression Syntax

Each line in a crontab follows this format:

    * * * * * command_to_execute
    │ │ │ │ │
    │ │ │ │ └─── Day of week (0-7, where both 0 and 7 represent Sunday)
    │ │ │ └───── Month (1-12)
    │ │ └─────── Day of month (1-31)
    │ └───────── Hour (0-23)
    └─────────── Minute (0-59)

Each asterisk (*) means "every possible value." You can replace asterisks with specific numbers, ranges, or intervals.

## Common Cron Patterns

Run every day at 2:30 AM:

    30 2 * * * /home/user/backup.sh

Run every Monday at 9:00 AM:

    0 9 * * 1 /home/user/weekly_report.sh

Run every 15 minutes:

    */15 * * * * /home/user/check_status.sh

Run on the first day of every month at midnight:

    0 0 1 * * /home/user/monthly_cleanup.sh

## Special Strings

Cron also supports convenient shortcuts:

- `@reboot` — Run once at system startup
- `@daily` or `@midnight` — Run once a day at midnight
- `@weekly` — Run once a week at midnight on Sunday
- `@monthly` — Run on the first day of each month at midnight
- `@yearly` or `@annually` — Run once a year at midnight on January 1

Example:

    @daily /home/user/daily_backup.sh

Illustrated clock face with five concentric rings representing the five cron time fields, showing how cron expressions map to calendar time with visual indicators for minute, hour, day, month, and weekday

#### 💡 Key Takeaways

- Cron daemon runs continuously, executing scheduled tasks automatically
- Each user maintains a personal crontab edited with 'crontab -e'
- Cron expressions use five time fields: minute, hour, day, month, weekday
- Special strings like @daily and @reboot provide convenient shortcuts

## Shell Scripting Fundamentals

## What Is a Shell Script?

A shell script is a text file containing a series of commands that the shell executes sequentially. Scripts automate tasks that would otherwise require typing multiple commands manually. They're the backbone of Linux automation.

Every shell script begins with a shebang line that tells the system which interpreter to use:

    #!/bin/bash

This line must be the first line of the script. It specifies that bash should execute the commands that follow.

## Creating Your First Script

Create a file named `hello.sh`:

    #!/bin/bash
    # This is a comment
    echo "Hello, Linux administrator!"
    date
    whoami

The script includes three commands that will execute in order: displaying a message, showing the current date and time, and displaying the current username.

## Making Scripts Executable

New script files aren't executable by default. Grant execute permission:

    chmod +x hello.sh

Now run the script:

    ./hello.sh

The `./` prefix tells the shell to execute the file in the current directory.

## Variables in Bash

Variables store data for use throughout your script:

    #!/bin/bash
    BACKUP_DIR="/opt/backups"
    DATE=$(date +%Y%m%d)
    FILENAME="backup_${DATE}.tar.gz"

    echo "Creating backup: $FILENAME"
    echo "Destination: $BACKUP_DIR"

Variable names are case-sensitive by convention and typically use UPPERCASE for constants. Access variable values by prefixing the name with `$`.

## Command Substitution

Capture command output and store it in a variable using `$()` syntax:

    CURRENT_USER=$(whoami)
    HOSTNAME=$(hostname)
    FREE_SPACE=$(df -h / | tail -1 | awk '{print $4}')

## Basic Output and Input

The `echo` command displays text:

    echo "Starting backup process..."
    echo "Backup completed successfully"

The `read` command captures user input:

    echo "Enter your name:"
    read USERNAME
    echo "Hello, $USERNAME!"

## Script Structure Best Practices

1. Start with a shebang: Always include `#!/bin/bash`
2. Add comments: Explain what the script does and why
3. Use meaningful variable names: `BACKUP_DIR` is better than `BD`
4. Group related commands: Keep logical sections together
5. Include error checking: Verify commands succeed before continuing

Illustrated journey showing evolution from single command to complete script, depicted as stepping stones across a stream where each stone represents a stage: manual command, saved command, script with variables, script with logic

#### 💡 Key Takeaways

- Shell scripts automate command sequences and begin with #!/bin/bash shebang
- Use chmod +x to make scripts executable, then run with ./scriptname.sh
- Variables store data; access them with $ prefix (e.g., $BACKUP_DIR)
- Command substitution $() captures output for use in scripts

## Control Structures: Making Scripts Intelligent

## Conditional Logic with if Statements

Conditionals allow scripts to make decisions based on conditions. The basic syntax:

    if [ condition ]; then
        # commands to run if condition is true
    fi

Example: Check if directory exists

    BACKUP_DIR="/opt/backups"

    if [ -d "$BACKUP_DIR" ]; then
        echo "Backup directory exists"
    else
        echo "Creating backup directory..."
        mkdir -p "$BACKUP_DIR"
    fi

## Common Test Conditions

File tests:

- `-f file` — File exists and is a regular file
- `-d directory` — Directory exists
- `-r file` — File is readable
- `-w file` — File is writable
- `-x file` — File is executable

String comparisons:

- `"$str1" = "$str2"` — Strings are equal
- `"$str1" != "$str2"` — Strings are not equal
- `-z "$str"` — String is empty
- `-n "$str"` — String is not empty

Numeric comparisons:

- `$num1 -eq $num2` — Equal
- `$num1 -ne $num2` — Not equal
- `$num1 -lt $num2` — Less than
- `$num1 -gt $num2` — Greater than

## Loops: Repeating Tasks

For loops iterate over lists:

    for file in /var/log/*.log; do
        echo "Processing $file"
        gzip "$file"
    done

While loops repeat while a condition is true:

    COUNTER=1
    while [ $COUNTER -le 5 ]; do
        echo "Attempt $COUNTER"
        COUNTER=$((COUNTER + 1))
    done

## Practical Example: Disk Space Monitor

    #!/bin/bash
    # Monitor disk space and alert if usage exceeds threshold

    THRESHOLD=80
    USAGE=$(df -h / | tail -1 | awk '{print $5}' | sed 's/%//')

    if [ $USAGE -gt $THRESHOLD ]; then
        echo "WARNING: Disk usage is ${USAGE}%"
        echo "Threshold exceeded: ${THRESHOLD}%"
        # Send alert email
        echo "Disk space critical on $(hostname)" | mail -s "Disk Alert" root
    else
        echo "Disk usage OK: ${USAGE}%"
    fi

This script checks disk usage, compares it to a threshold, and sends an email alert if space is running low.

## Exit Codes and Error Handling

Every command returns an exit code: 0 for success, non-zero for failure. Check the last command's exit code with `$?`:

    mkdir /opt/backups
    if [ $? -eq 0 ]; then
        echo "Directory created successfully"
    else
        echo "Failed to create directory"
        exit 1
    fi

Use `exit` to terminate scripts with a specific code, allowing other scripts or cron to detect failures.

Illustrated decision tree showing a script's logic flow as a path through a forest where different conditions lead to different outcomes, with branches representing if/else decisions and loops shown as circular paths

#### 💡 Key Takeaways

- If statements enable scripts to make decisions based on conditions
- Test conditions check files (-d, -f), strings (=, !=), and numbers (-eq, -gt)
- For loops iterate over lists; while loops repeat until a condition fails
- Exit codes (0=success, non-zero=failure) enable error handling

## File Manipulation and System Maintenance Scripts

## Working with Files in Scripts

Scripts frequently need to create, modify, move, or delete files. Bash provides powerful commands for file manipulation.

Creating and writing to files:

    # Overwrite file with new content
    echo "Backup started at $(date)" > /var/log/backup.log

    # Append to existing file
    echo "Backup completed at $(date)" >> /var/log/backup.log

Copying and moving files with timestamps:

    SOURCE="/etc/important.conf"
    BACKUP_DIR="/opt/backups"
    TIMESTAMP=$(date +%Y%m%d_%H%M%S)

    cp "$SOURCE" "${BACKUP_DIR}/important.conf.${TIMESTAMP}"

Finding and processing files:

    # Find log files older than 30 days and compress them
    find /var/log -name "*.log" -mtime +30 -exec gzip {} \;

    # Delete compressed logs older than 90 days
    find /var/log -name "*.gz" -mtime +90 -delete

## Practical Backup Script Example

    #!/bin/bash
    # Automated backup script for critical directories

    BACKUP_SOURCE="/home /etc /var/www"
    BACKUP_DEST="/opt/backups"
    DATESUFFIX=$(date +%Y%m%d_%H%M%S)
    BACKUP_FILE="system_backup_${DATESUFFIX}.tar.gz"
    LOGFILE="/var/log/backup.log"

    # Create backup directory if it doesn't exist
    if [ ! -d "$BACKUP_DEST" ]; then
        mkdir -p "$BACKUP_DEST"
    fi

    # Log backup start
    echo "[$(date)] Starting backup..." >> "$LOGFILE"

    # Create compressed archive
    tar -czf "${BACKUP_DEST}/${BACKUP_FILE}" $BACKUP_SOURCE 2>> "$LOGFILE"

    if [ $? -eq 0 ]; then
        echo "[$(date)] Backup completed: $BACKUP_FILE" >> "$LOGFILE"
        # Remove backups older than 7 days
        find "$BACKUP_DEST" -name "system_backup_*.tar.gz" -mtime +7 -delete
    else
        echo "[$(date)] Backup FAILED" >> "$LOGFILE"
        exit 1
    fi

## Log Rotation Script

    #!/bin/bash
    # Rotate application logs to prevent disk space issues

    LOG_DIR="/var/log/myapp"
    ARCHIVE_DIR="${LOG_DIR}/archive"
    DATE=$(date +%Y%m%d)

    mkdir -p "$ARCHIVE_DIR"

    for logfile in "${LOG_DIR}"/*.log; do
        if [ -f "$logfile" ]; then
            # Compress and move to archive
            gzip -c "$logfile" > "${ARCHIVE_DIR}/$(basename $logfile).${DATE}.gz"
            # Clear original log file
            > "$logfile"
        fi
    done

    # Keep only last 30 days of archives
    find "$ARCHIVE_DIR" -name "*.gz" -mtime +30 -delete

## System Health Check Script

    #!/bin/bash
    # Monitor system resources and alert on issues

    REPORT="/tmp/health_report.txt"

    echo "System Health Report - $(date)" > "$REPORT"
    echo "==========================================" >> "$REPORT"

    # Check disk usage
    echo -e "\nDisk Usage:" >> "$REPORT"
    df -h >> "$REPORT"

    # Check memory usage
    echo -e "\nMemory Usage:" >> "$REPORT"
    free -h >> "$REPORT"

    # Check system load
    echo -e "\nSystem Load:" >> "$REPORT"
    uptime >> "$REPORT"

    # Email report
    mail -s "Daily Health Report" admin@example.com < "$REPORT"

Illustrated automated factory assembly line where files move along conveyor belts through different processing stations: backup creation, compression, archiving, and cleanup, showing the systematic approach to file maintenance

#### 💡 Key Takeaways

- Use > to overwrite files, >> to append; both support command substitution
- Combine find with -exec or -delete for powerful bulk file operations
- Backup scripts should include timestamps, logging, and old file cleanup
- System maintenance scripts automate log rotation, health checks, and alerts

## Bringing It All Together: Automation Best Practices

## Combining Cron and Scripts

The power of Linux automation emerges when you combine cron's scheduling with shell script logic. This pairing enables sophisticated automated workflows that run reliably without supervision.

Typical automation workflow:

1. Write a shell script that performs a specific task
2. Test the script thoroughly by running it manually
3. Make the script executable with `chmod +x`
4. Add a crontab entry to schedule regular execution
5. Monitor logs to ensure the automation works correctly

Example crontab for complete automation:

    # Daily backup at 2:00 AM
    0 2 * * * /opt/scripts/backup.sh >> /var/log/backup.log 2>&1

    # Log rotation every Sunday at 3:00 AM
    0 3 * * 0 /opt/scripts/rotate_logs.sh

    # Disk space check every 6 hours
    0 */6 * * * /opt/scripts/check_disk.sh

    # Monthly system report on the 1st at 6:00 AM
    0 6 1 * * /opt/scripts/monthly_report.sh

The `>> /var/log/backup.log 2>&1` redirects both standard output and errors to a log file, creating an audit trail.

## Essential Best Practices

Use absolute paths in scripts:

    # Good: Explicit path
    /usr/bin/tar -czf /opt/backups/data.tar.gz /home/data

    # Risky: Relies on PATH environment variable
    tar -czf backups/data.tar.gz data

Cron jobs run with minimal environment variables. Always specify complete paths to commands and files.

Implement proper logging:

    LOGFILE="/var/log/myscript.log"

    log_message() {
        echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" >> "$LOGFILE"
    }

    log_message "Script started"
    log_message "Processing data..."
    log_message "Script completed successfully"

Handle errors gracefully:

    set -e  # Exit immediately if any command fails
    set -u  # Treat unset variables as errors
    set -o pipefail  # Catch errors in pipelines

    # Or use explicit error checking
    if ! command_that_might_fail; then
        echo "Error: Command failed" | mail -s "Script Alert" admin@example.com
        exit 1
    fi

Test before deploying:

- Run scripts manually before scheduling them
- Test with various conditions (full disk, missing files, network issues)
- Verify log files capture important information
- Confirm email alerts work correctly

## Security Considerations

Set appropriate permissions:

    # Script readable and executable only by owner
    chmod 700 /opt/scripts/sensitive_backup.sh

    # Log file writable only by owner
    chmod 600 /var/log/private.log

Avoid storing passwords in scripts:

    # Bad: Password visible in script
    mysql -u root -pSecretPassword123

    # Better: Use configuration file with restricted permissions
    mysql --defaults-extra-file=/root/.mysql_credentials

## Documentation and Maintenance

Document your automation setup:

- Maintain a list of all scheduled jobs
- Comment scripts explaining their purpose
- Note dependencies (required commands, files, services)
- Record contact information for alerts
- Keep a change log when modifying scripts

Regularly review your automation:

- Check logs for errors or warnings
- Verify backups are actually created and valid
- Update scripts when system configurations change
- Remove obsolete automation tasks

Illustrated control room with administrator monitoring multiple automated systems shown as dashboard panels, with indicators showing successful automated backups, scheduled tasks running smoothly, and alert systems standing ready

#### 💡 Key Takeaways

- Combine cron scheduling with shell scripts for powerful automation workflows
- Use absolute paths, implement logging, and handle errors gracefully
- Test scripts thoroughly before scheduling with cron
- Document automation setup and review logs regularly for issues

## 🔬 Automating System Maintenance with Cron and Shell Scripts

Objective: Create and schedule automated system maintenance scripts using bash scripting and cron jobs to perform routine administrative tasks

⏱ Estimated time: 45 minutes💻 Platform: Ubuntu Linux VM on VirtualBox (Windows host)
Prerequisites:

- Ubuntu Linux VM running on VirtualBox
- Administrative (sudo) access to the VM
- Basic familiarity with the terminal and text editors

### Procedures

1 Open your Ubuntu VM in VirtualBox and launch the terminal application

1. Start VirtualBox on your Windows computer
2. Select your Ubuntu VM from the list
3. Click the Start button (green arrow)
4. Once Ubuntu boots, log in with your credentials
5. Press `Ctrl+Alt+T` to open the terminal, or click Activities > search for Terminal > click the Terminal icon

✓ Expected Output

    A terminal window opens displaying a command prompt similar to:
    ```
    username@ubuntu:~$
    ```

🔍 Verify: The terminal prompt shows your username, hostname, and current directory (~)
2 Create a dedicated directory structure for lab files and navigate to it

Execute these commands to create and navigate to the lab directory:

    mkdir -p ~/admin-automation/scripts
    mkdir ~/admin-automation/logs
    mkdir ~/admin-automation/backups
    cd ~/admin-automation

The `-p` flag creates parent directories as needed. This structure organizes scripts, logs, and backup files separately.

✓ Expected Output

    ```
    username@ubuntu:~$ mkdir -p ~/admin-automation/scripts
    username@ubuntu:~$ mkdir ~/admin-automation/logs
    username@ubuntu:~$ mkdir ~/admin-automation/backups
    username@ubuntu:~$ cd ~/admin-automation
    username@ubuntu:~/admin-automation$
    ```

🔍 Verify: Run `pwd` to confirm you're in `/home/username/admin-automation` and run `ls` to see the three directories: backups, logs, scripts
3 Create a shell script that performs system disk space monitoring

Use the nano text editor to create a new script file:

    nano scripts/disk_monitor.sh

Type the following script content exactly:

    #!/bin/bash
    # Disk Space Monitoring Script
    # Logs disk usage and alerts if usage exceeds threshold

    LOG_FILE="$HOME/admin-automation/logs/disk_usage.log"
    THRESHOLD=80
    DATE=$(date '+%Y-%m-%d %H:%M:%S')

    echo "=== Disk Usage Report: $DATE ===" >> "$LOG_FILE"
    df -h / | tail -n 1 >> "$LOG_FILE"

    USAGE=$(df / | tail -n 1 | awk '{print $5}' | sed 's/%//')

    if [ "$USAGE" -gt "$THRESHOLD" ]; then
        echo "WARNING: Disk usage is at ${USAGE}% (threshold: ${THRESHOLD}%)" >> "$LOG_FILE"
    else
        echo "OK: Disk usage is at ${USAGE}% (threshold: ${THRESHOLD}%)" >> "$LOG_FILE"
    fi

    echo "" >> "$LOG_FILE"

Press `Ctrl+O` to save, then `Enter` to confirm the filename, then `Ctrl+X` to exit nano.

✓ Expected Output

    The nano editor opens. After saving and exiting, you return to the command prompt with no error messages.

🔍 Verify: Run `cat scripts/disk_monitor.sh` to verify the file was created and contains the script content
4 Make the disk monitoring script executable

Add execute permissions to the script:

    chmod +x scripts/disk_monitor.sh

The `chmod +x` command adds execute permission, allowing the script to run as a program. Verify the permissions changed:

    ls -l scripts/disk_monitor.sh

✓ Expected Output

    ```
    username@ubuntu:~/admin-automation$ chmod +x scripts/disk_monitor.sh
    username@ubuntu:~/admin-automation$ ls -l scripts/disk_monitor.sh
    -rwxrwxr-x 1 username username 512 Jan 15 10:30 scripts/disk_monitor.sh
    ```

    Notice the `x` characters in the permissions string, indicating execute permission.

🔍 Verify: The permissions string shows `-rwxrwxr-x` with at least one `x` present, and the file is displayed in green when using `ls --color`
5 Test the disk monitoring script manually

Execute the script to ensure it works correctly:

    ./scripts/disk_monitor.sh

Then check the log file it created:

    cat logs/disk_usage.log

✓ Expected Output

    ```
    username@ubuntu:~/admin-automation$ ./scripts/disk_monitor.sh
    username@ubuntu:~/admin-automation$ cat logs/disk_usage.log
    === Disk Usage Report: 2024-01-15 10:35:42 ===
    /dev/sda1        20G  8.5G   11G  45% /
    OK: Disk usage is at 45% (threshold: 80%)

    ```

    The actual disk usage percentage will vary based on your VM's disk usage.

🔍 Verify: The log file exists, contains a timestamp, shows disk usage information with a filesystem path, and displays either OK or WARNING status
6 Create a second script that performs system updates check

Create another maintenance script:

    nano scripts/update_check.sh

Enter this script content:

    #!/bin/bash
    # System Updates Check Script
    # Checks for available system updates and logs the count

    LOG_FILE="$HOME/admin-automation/logs/update_check.log"
    DATE=$(date '+%Y-%m-%d %H:%M:%S')

    echo "=== Update Check: $DATE ===" >> "$LOG_FILE"

    # Update package lists
    sudo apt-get update > /dev/null 2>&1

    # Count available updates
    UPDATES=$(apt list --upgradable 2>/dev/null | grep -c "upgradable")

    if [ "$UPDATES" -gt 0 ]; then
        echo "$UPDATES package(s) available for update" >> "$LOG_FILE"
        apt list --upgradable 2>/dev/null | grep "upgradable" >> "$LOG_FILE"
    else
        echo "System is up to date" >> "$LOG_FILE"
    fi

    echo "" >> "$LOG_FILE"

Save and exit nano (`Ctrl+O`, `Enter`, `Ctrl+X`).

✓ Expected Output

    The nano editor opens and closes without errors after saving.

🔍 Verify: Run `cat scripts/update_check.sh` to verify the file contains the script
7 Make the update check script executable and test it

Add execute permissions and run the script:

    chmod +x scripts/update_check.sh
    ./scripts/update_check.sh

You'll be prompted for your sudo password. Enter it to allow the script to update package lists.

Then view the results:

    cat logs/update_check.log

✓ Expected Output

    ```
    username@ubuntu:~/admin-automation$ chmod +x scripts/update_check.sh
    username@ubuntu:~/admin-automation$ ./scripts/update_check.sh
    [sudo] password for username:
    username@ubuntu:~/admin-automation$ cat logs/update_check.log
    === Update Check: 2024-01-15 10:40:15 ===
    3 package(s) available for update
    libc6/jammy-updates 2.35-0ubuntu3.6 amd64 [upgradable from: 2.35-0ubuntu3.5]
    libssl3/jammy-updates 3.0.2-0ubuntu1.12 amd64 [upgradable from: 3.0.2-0ubuntu1.11]
    openssl/jammy-updates 3.0.2-0ubuntu1.12 amd64 [upgradable from: 3.0.2-0ubuntu1.11]

    ```

    The number and names of updates will vary based on your system's current state.

🔍 Verify: The log file contains a timestamp, shows either a count of available updates or states the system is up to date
8 View your current user's crontab file

Check if you have any existing cron jobs:

    crontab -l

The `-l` flag lists current cron jobs. If you have no crontab yet, you'll see an error message, which is normal for first-time users.

✓ Expected Output

    Either:
    ```
    no crontab for username
    ```

    Or if you have existing entries:
    ```
    # Existing cron job entries would appear here
    ```

🔍 Verify: The command executes without permission errors
9 Create a crontab to schedule the disk monitoring script

Open the crontab editor:

    crontab -e

If this is your first time, you'll be prompted to select an editor. Choose option 1 for nano by typing `1` and pressing `Enter`.

Add these lines at the end of the file:

    # Run disk monitoring every 30 minutes
    */30 * * * * /home/username/admin-automation/scripts/disk_monitor.sh

    # Run update check daily at 8:00 AM
    0 8 * * * /home/username/admin-automation/scripts/update_check.sh

Important: Replace `username` with your actual Ubuntu username.

The cron syntax is: `minute hour day month weekday command`

- `*/30 * * * *` means every 30 minutes
- `0 8 * * *` means at 8:00 AM daily

Save and exit (`Ctrl+O`, `Enter`, `Ctrl+X`).

✓ Expected Output

    ```
    no crontab for username - using an empty one

    Select an editor.  To change later, run 'select-editor'.
      1. /bin/nano        <---- easiest
      2. /usr/bin/vim.basic
      3. /usr/bin/vim.tiny

    Choose 1-3 [1]: 1
    ```

    After saving:
    ```
    crontab: installing new crontab
    ```

🔍 Verify: Run `crontab -l` and verify your two cron entries appear in the list
10 Verify the cron daemon is running

Check the status of the cron service:

    systemctl status cron

Look for "active (running)" in the output. If the service is not running, start it:

    sudo systemctl start cron

Press `q` to exit the status display.

✓ Expected Output

    ```
    ● cron.service - Regular background program processing daemon
         Loaded: loaded (/lib/systemd/system/cron.service; enabled; vendor preset: enabled)
         Active: active (running) since Mon 2024-01-15 09:15:23 UTC; 2h ago
           Docs: man:cron(8)
       Main PID: 712 (cron)
          Tasks: 1 (limit: 4557)
         Memory: 1.2M
            CPU: 45ms
         CGroup: /system.slice/cron.service
                 └─712 /usr/sbin/cron -f -P
    ```

🔍 Verify: The output shows "Active: active (running)" in green text
11 Create a manual backup script for testing

Create a script that backs up the log files:

    nano scripts/backup_logs.sh

Enter this content:

    #!/bin/bash
    # Backup Script for Log Files
    # Creates timestamped archive of log files

    BACKUP_DIR="$HOME/admin-automation/backups"
    LOG_DIR="$HOME/admin-automation/logs"
    DATE=$(date '+%Y%m%d_%H%M%S')
    BACKUP_FILE="logs_backup_${DATE}.tar.gz"

    if [ -d "$LOG_DIR" ] && [ "$(ls -A $LOG_DIR)" ]; then
        tar -czf "${BACKUP_DIR}/${BACKUP_FILE}" -C "$HOME/admin-automation" logs/
        echo "Backup created: ${BACKUP_FILE}"
        echo "Backup size: $(du -h ${BACKUP_DIR}/${BACKUP_FILE} | cut -f1)"
    else
        echo "No log files to backup"
    fi

Save and exit nano.

✓ Expected Output

    The nano editor closes after saving without errors.

🔍 Verify: Run `cat scripts/backup_logs.sh` to verify the file contents
12 Make the backup script executable and test it

Add execute permissions and run the backup script:

    chmod +x scripts/backup_logs.sh
    ./scripts/backup_logs.sh

Then verify the backup was created:

    ls -lh backups/

✓ Expected Output

    ```
    username@ubuntu:~/admin-automation$ chmod +x scripts/backup_logs.sh
    username@ubuntu:~/admin-automation$ ./scripts/backup_logs.sh
    Backup created: logs_backup_20240115_104512.tar.gz
    Backup size: 4.0K
    username@ubuntu:~/admin-automation$ ls -lh backups/
    total 4.0K
    -rw-rw-r-- 1 username username 876 Jan 15 10:45 logs_backup_20240115_104512.tar.gz
    ```

🔍 Verify: A `.tar.gz` file appears in the backups directory with a timestamp in its name
13 Add the backup script to run weekly via cron

Edit your crontab again:

    crontab -e

Add this line at the end:

    # Run log backup every Sunday at 11:00 PM
    0 23 * * 0 /home/username/admin-automation/scripts/backup_logs.sh

Important: Replace `username` with your actual username.

The `0 23 * * 0` means:

- `0` - minute 0
- `23` - hour 23 (11 PM)
- `*` - any day of month
- `*` - any month
- `0` - Sunday (0=Sunday, 1=Monday, etc.)

Save and exit.

✓ Expected Output

    ```
    crontab: installing new crontab
    ```

🔍 Verify: Run `crontab -l` and verify all three cron entries are present
14 Test a cron job by setting it to run in the next few minutes

First, check the current time:

    date '+%H:%M'

Note the current time. Now edit your crontab:

    crontab -e

Add a temporary test entry that runs 2 minutes from now. For example, if the current time is 10:45, add:

    # Temporary test job - delete after verification
    47 10 * * * /home/username/admin-automation/scripts/disk_monitor.sh

Replace `47 10` with a time 2 minutes in the future from your current time, and replace `username` with your username.

Save and exit. Wait for the specified time to pass (about 2 minutes), then check the log:

    tail logs/disk_usage.log

✓ Expected Output

    After waiting, you should see a new entry in the log file with a timestamp matching when the cron job ran:

    ```
    === Disk Usage Report: 2024-01-15 10:47:01 ===
    /dev/sda1        20G  8.5G   11G  45% /
    OK: Disk usage is at 45% (threshold: 80%)

    ```

🔍 Verify: The log file shows a new entry with a timestamp matching the cron schedule time (within 1 minute)
15 Clean up the test cron job and review the final configuration

Remove the temporary test entry:

    crontab -e

Delete the line with the comment `# Temporary test job - delete after verification` and the line below it. Save and exit.

View your final crontab:

    crontab -l

Verify all your script files:

    ls -lh scripts/

Check that log files exist:

    ls -lh logs/

✓ Expected Output

    ```
    username@ubuntu:~/admin-automation$ crontab -l
    # Run disk monitoring every 30 minutes
    */30 * * * * /home/username/admin-automation/scripts/disk_monitor.sh

    # Run update check daily at 8:00 AM
    0 8 * * * /home/username/admin-automation/scripts/update_check.sh

    # Run log backup every Sunday at 11:00 PM
    0 23 * * 0 /home/username/admin-automation/scripts/backup_logs.sh

    username@ubuntu:~/admin-automation$ ls -lh scripts/
    total 12K
    -rwxrwxr-x 1 username username 445 Jan 15 10:50 backup_logs.sh
    -rwxrwxr-x 1 username username 512 Jan 15 10:30 disk_monitor.sh
    -rwxrwxr-x 1 username username 498 Jan 15 10:38 update_check.sh

    username@ubuntu:~/admin-automation$ ls -lh logs/
    total 8.0K
    -rw-rw-r-- 1 username username 423 Jan 15 10:47 disk_usage.log
    -rw-rw-r-- 1 username username 512 Jan 15 10:40 update_check.log
    ```

🔍 Verify: Three cron entries are active, three executable scripts exist, and at least two log files contain data

### ⚠️ Troubleshooting

Script shows 'Permission denied' error when executing

The script lacks execute permission. Run `chmod +x scriptname.sh` to add execute permission. Verify with `ls -l scriptname.sh` - you should see 'x' characters in the permissions string.

Cron job doesn't execute - no new log entries appear

Check several things: 1) Verify cron is running with `systemctl status cron`. 2) Ensure you used absolute paths in crontab (starting with /home/username), not relative paths. 3) Check for cron errors with `grep CRON /var/log/syslog`. 4) Verify your username is correct in the paths. 5) Test the script manually first with `./scripts/scriptname.sh` to ensure it works.

Nano editor shows '^O' and '^X' but these keys don't work

The ^ symbol means the Ctrl key. Press Ctrl+O (not Shift+6 followed by O) to save, and Ctrl+X to exit. Hold down the Ctrl key while pressing the letter key.

Script creates empty log files with no content

Check if the script has permission issues or wrong paths. Run the script manually with `bash -x ./scripts/scriptname.sh` to see detailed execution output. Verify the LOG_FILE variable points to the correct directory and that the directory exists.

Crontab editor shows 'command not found' error

You must use absolute paths in crontab entries. Instead of `~/admin-automation/scripts/script.sh`, use `/home/yourusername/admin-automation/scripts/script.sh`. Cron doesn't expand the ~ shortcut. Find your home directory path with `echo $HOME` and use that full path.

### 🏆 Create an Automated System Health Report

Apply what you learned — complete this task without step-by-step guidance.

Build a comprehensive system health monitoring script and schedule it to run automatically.

Your challenge is to create a script named `system_health.sh` that generates a single report containing:

- Current system uptime
- Memory usage (total, used, and free)
- Top 5 processes by memory usage
- Top 5 processes by CPU usage
- Current logged-in users
- Number of running processes
- Available disk space on all mounted filesystems

The script should:

- Save the report to `logs/system_health.log` with a timestamp
- Append to the existing log file (don't overwrite previous reports)
- Include clear section headers and formatting for readability
- Use proper bash scripting practices including variables and comments

Schedule this script to run:

- Every 6 hours during the day (6 AM, 12 PM, 6 PM)
- Using a single cron expression

Test your script manually before scheduling it. Verify that multiple runs append to the log file without overwriting previous reports. Confirm the cron job executes by checking the log file after the scheduled time.

Hint: Research these commands: `uptime`, `free -h`, `ps aux --sort=-%mem`, `ps aux --sort=-%cpu`, `who`, `ps aux | wc -l`, and `df -h`.

I have completed this lab exercise

## 📝 Knowledge Check

Test your understanding of the material covered in this module. Select the best answer for each question.

#### Question 1

Which cron expression schedules a job to run every day at 3:45 AM?

A) 45 3 * * * B) 3 45 * * * C) * * 3 45 * D) 45 * * * 3

#### Question 2

What command makes a shell script named backup.sh executable?

A) execute backup.sh B) chmod +x backup.sh C) run backup.sh D) enable backup.sh

#### Question 3

In bash scripting, how do you access the value stored in a variable named BACKUP_DIR?

A) BACKUP_DIR B) $BACKUP_DIR C) @BACKUP_DIR D) &BACKUP_DIR

#### Question 4

Which test condition checks if a directory named /opt/backups exists?

A) [ -f /opt/backups ] B) [ -d /opt/backups ] C) [ -e /opt/backups ] D) [ -x /opt/backups ]

#### Question 5

What does the cron special string @daily mean?

A) Run every hour during the day B) Run once a day at midnight C) Run every weekday at 9 AM D) Run once per business day

#### Question 6

In a bash script, what does the line '#!/bin/bash' accomplish?

A) It adds a comment explaining the script purpose B) It specifies which interpreter should execute the script C) It sets the script's default working directory D) It defines the script's output destination

#### Question 7

What happens if a command in a cron job fails?

A) Cron sends an email notification automatically B) The cron job is disabled until manually re-enabled C) Cron continues and will run the job again at the next scheduled time D) All subsequent cron jobs are cancelled

#### Question 8

Which command sequence captures the output of the 'date' command and stores it in a variable named TODAY?

A) TODAY = date B) TODAY=$(date) C) TODAY=[date] D) TODAY=`date

## 🎯 Module Summary

This module covered Linux automation fundamentals, including the cron scheduling system and shell scripting essentials. You learned how to create crontab entries using cron expressions to schedule automated tasks at specific times or intervals. Shell scripting basics included variables, command substitution, conditional logic with if statements, and loops for repeating operations. The module demonstrated practical automation scenarios including backup scripts, log rotation, and system health monitoring. By combining cron scheduling with well-designed shell scripts that implement proper logging, error handling, and security practices, administrators can create reliable automated workflows that maintain Linux systems efficiently with minimal manual intervention.

### Learning Objectives — Review

- Schedule automated tasks using cron and crontab
- Create basic shell scripts for administrative tasks
- Implement system maintenance procedures
- Execute routine administrative workflows efficiently

🎉

### Module Complete!

You have completed all sections of this module.