Learn 🧠 All Concepts (20) 🤖 What is an LLM? 📚 RAG Explained ⚡ AI Agents 💻 Run AI Locally 🇮🇳 AI in India 📖 Learn Tracks 🔧 DevOps Track ⚙️ AI Ops Track 🗺️ AI Engineer Roadmap
Tools 🔧 AI Tools Directory 🔓 Open Source AI ⭐ Top GitHub Repos ✦ Claude Skill Repos 🚀 Ready-to-Deploy Projects
Build 🏗️ Build Hub 🎯 Master Prompts 🧩 RAG Agents 🚀 App Megaprompts
Workflows ⚡ All Workflows (22) 🎥 Text to Video 🎞️ Image to Video 🔊 Text to Speech ♻️ Automation
Resources 🧪 Colab Notebooks ⚙️ n8n Workflows 📈 Algo Trading 💰 Passive Income
🗂️ Browse All Topics About AItheGuru
Learn Linux for Production Support Meena automates the morning checklist
Linux for Production Support Ch 13 / 32 Advanced
⚙️

Meena automates the morning checklist

Shell scripting, functions, loops — turn manual work into automation

⏱ 14 min 6 commands 5 takeaways
⚙️
In this chapter
Meena
Senior DevOps engineer, e-commerce platform
The story

Meena had been doing the same 15-minute manual health check every morning for 4 months. One Thursday she decided to automate it.

Any task you do more than twice should be a script.

Your first script:

#!/bin/bash
# The shebang line - always first. Tells Linux to use bash.
echo "Hello from my first script"
echo "Running as: $(whoami) on $(hostname)"
echo "Time: $(date)"

Save as hello.sh, then:

chmod +x hello.sh    # make it executable
./hello.sh           # run it
bash -x hello.sh     # debug mode - prints every command as it runs

Variables and if/else:

#!/bin/bash
set -euo pipefail    # always add this - exits on any error safely
APP="payment-service"
TODAY=$(date +%Y-%m-%d)
DISK=$(df / | awk 'NR==2{print $5}' | tr -d '%')
if [ "$DISK" -gt 90 ]; then
    echo "CRITICAL: Disk at ${DISK}%"
    exit 1
elif [ "$DISK" -gt 80 ]; then
    echo "WARNING: Disk at ${DISK}%"
else
    echo "OK: Disk at ${DISK}%"
fi

Number comparisons: -gt (greater than), -lt (less than), -eq (equal), -ne (not equal).

File checks: -f (file exists), -d (directory exists), -z (string empty).

Loops:

# Check multiple servers:
for SERVER in web-01 web-02 web-03; do
    ping -c 1 $SERVER > /dev/null 2>&1 && echo "$SERVER: UP" || echo "$SERVER: DOWN"
done
# Wait for app after deployment (up to 3 minutes):
for i in {1..18}; do
    HTTP=$(curl -s -o /dev/null -w "%{http_code}" http://localhost:8080/health)
    [ "$HTTP" = "200" ] && echo "App is UP!" && exit 0
    echo "Attempt $i/18 - waiting 10 seconds"
    sleep 10
done
echo "App did not come up in 3 minutes"
exit 1

Meena's morning health check script:

#!/bin/bash
set -euo pipefail
SERVICES="payment-svc inventory-svc cart-svc"
LOG_DIR="/opt/app/logs"
STATUS="OK"
log() { echo "[$(date '+%H:%M:%S')] $*"; }
check_disk() {
    local USAGE
    USAGE=$(df / | awk 'NR==2{print $5}' | tr -d '%')
    if [ "$USAGE" -gt 85 ]; then
        STATUS="CRITICAL"
        log "CRITICAL: Disk at ${USAGE}%"
    else
        log "OK: Disk at ${USAGE}%"
    fi
}
check_services() {
    for SVC in $SERVICES; do
        if systemctl is-active --quiet "$SVC"; then
            log "OK: $SVC running"
        else
            STATUS="CRITICAL"
            log "DOWN: $SVC is not running!"
        fi
    done
}
log "=== Morning health check ==="
check_disk
check_services
log "Final status: $STATUS"
[ "$STATUS" = "OK" ] && exit 0 || exit 1

Scheduled with cron at 7:30am. Four months of manual work, automated in 2 hours.

Golden rules for production scripts:

1. set -euo pipefail - fails safely on any error

2. cp file file.bak.$(date +%Y%m%d) - backup before every change

3. Log with timestamps

4. Always exit 1 on failure so callers know

5. bash -x script.sh for debugging

Key takeaways

set -euo pipefail at the top of every production script — fail safely

$? is the exit code of the last command — 0 means success, non-zero means failure

Local variables inside functions avoid polluting global scope

bash -x script.sh prints every command as it runs — essential for debugging

chmod +x makes a script executable — required before running with ./

Commands from this chapter
$ chmod +x script.sh && ./script.sh
Make executable and run
$ bash -x script.sh
Debug mode — trace every command as it runs
$ bash -n script.sh
Syntax check without running
$ set -euo pipefail
Add to top of every production script
$ [ $? -eq 0 ] && echo "OK" || echo "FAILED"
Check if last command succeeded
$ cp config.xml config.xml.bak.$(date +%Y%m%d)
Backup with date before any change