Thursday, March 5, 2026

mount

#!/bin/sh
#############################################################################
# mount_monitor.sh
# Author      : Abdul Muqeet
# Description : Monitors mounted filesystems on Solaris 11.4.
#               Maintains a baseline of expected mount points and alerts
#               via HTML email when any deviation is detected.
# Usage       : mount_monitor.sh baseline   -- record current mounts
#               mount_monitor.sh monitor    -- compare against baseline
# Compatibility: /bin/sh (POSIX), Solaris 11.4 SPARC/x86
#############################################################################

#----------------------------------------------------------------------------
# CONFIGURATION — adjust these before deployment
#----------------------------------------------------------------------------
BASE_DIR="/var/tmp/mount_monitor"
BASELINE_FILE="${BASE_DIR}/df_mounts_baseline.txt"
CURRENT_FILE="${BASE_DIR}/df_mounts_current.txt"
HTML_REPORT="${BASE_DIR}/mount_report.html"
MAIL_TO="dba-alerts@yourcompany.com"
MAIL_FROM="noreply-mountmonitor@yourcompany.com"
SENDMAIL="/usr/sbin/sendmail"
#----------------------------------------------------------------------------

HOSTNAME_VAL=$(hostname)
TIMESTAMP=$(date "+%Y-%m-%d %H:%M:%S")
MODE="$1"

#----------------------------------------------------------------------------
# Helper: get sorted mount point list from df -h (column 6 = Mounted on)
#----------------------------------------------------------------------------
get_mounts() {
    df -h | awk 'NR>1 {print $6}' | sort
}

#----------------------------------------------------------------------------
# Helper: ensure BASE_DIR exists
#----------------------------------------------------------------------------
ensure_basedir() {
    if [ ! -d "${BASE_DIR}" ]; then
        mkdir -p "${BASE_DIR}"
        if [ $? -ne 0 ]; then
            echo "ERROR: Cannot create BASE_DIR: ${BASE_DIR}" >&2
            exit 1
        fi
    fi
}

#----------------------------------------------------------------------------
# BASELINE MODE
#----------------------------------------------------------------------------
run_baseline() {
    ensure_basedir
    get_mounts > "${BASELINE_FILE}"
    if [ $? -ne 0 ]; then
        echo "ERROR: Failed to write baseline file: ${BASELINE_FILE}" >&2
        exit 1
    fi
    COUNT=$(wc -l < "${BASELINE_FILE}" | tr -d ' ')
    echo "Baseline captured: ${COUNT} mount points stored in ${BASELINE_FILE}"
    echo "Timestamp: ${TIMESTAMP}"
}

#----------------------------------------------------------------------------
# BUILD HTML REPORT
#----------------------------------------------------------------------------
build_html() {
    MISSING_FILE="$1"
    NEW_FILE="$2"

    MISSING_COUNT=$(wc -l < "${MISSING_FILE}" | tr -d ' ')
    NEW_COUNT=$(wc -l    < "${NEW_FILE}"      | tr -d ' ')

    if [ "${MISSING_COUNT}" -gt 0 ]; then
        MISSING_STATUS='<span style="color:red;font-weight:bold;">YES (ALERT)</span>'
    else
        MISSING_STATUS='<span style="color:green;font-weight:bold;">NO</span>'
    fi

    if [ "${NEW_COUNT}" -gt 0 ]; then
        NEW_STATUS='<span style="color:orange;font-weight:bold;">YES</span>'
    else
        NEW_STATUS='<span style="color:green;font-weight:bold;">NO</span>'
    fi

    #--- Render missing mounts list ---
    if [ "${MISSING_COUNT}" -gt 0 ]; then
        MISSING_HTML=$(awk '{print "<li style=\"color:red\">" $0 "</li>"}' "${MISSING_FILE}")
    else
        MISSING_HTML='<li style="color:green">None</li>'
    fi

    #--- Render new mounts list ---
    if [ "${NEW_COUNT}" -gt 0 ]; then
        NEW_HTML=$(awk '{print "<li style=\"color:orange\">" $0 "</li>"}' "${NEW_FILE}")
    else
        NEW_HTML='<li style="color:green">None</li>'
    fi

    #--- Render baseline and current as <pre> blocks ---
    BASELINE_PRE=$(cat "${BASELINE_FILE}")
    CURRENT_PRE=$(cat "${CURRENT_FILE}")

    cat > "${HTML_REPORT}" << HTMLEOF
<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>Mount Monitor Alert - ${HOSTNAME_VAL}</title>
</head>
<body style="font-family:monospace;font-size:13px;">
  <h2 style="background:#333;color:#fff;padding:8px;">
    Mount Point Monitor Report
  </h2>
  <table border="1" cellpadding="5" cellspacing="0" style="border-collapse:collapse;">
    <tr><td><b>Hostname</b></td><td>${HOSTNAME_VAL}</td></tr>
    <tr><td><b>Check Time</b></td><td>${TIMESTAMP}</td></tr>
    <tr><td><b>Missing Mounts Detected</b></td><td>${MISSING_STATUS}</td></tr>
    <tr><td><b>New Mounts Detected</b></td><td>${NEW_STATUS}</td></tr>
  </table>

  <h3 style="color:red;">Missing Mount Points (in baseline but NOT currently mounted)</h3>
  <ul>${MISSING_HTML}</ul>

  <h3 style="color:orange;">New Mount Points (currently mounted but NOT in baseline)</h3>
  <ul>${NEW_HTML}</ul>

  <h3>Baseline Mount Points</h3>
  <pre style="background:#f4f4f4;padding:8px;border:1px solid #ccc;">${BASELINE_PRE}</pre>

  <h3>Current Mount Points</h3>
  <pre style="background:#f4f4f4;padding:8px;border:1px solid #ccc;">${CURRENT_PRE}</pre>

  <p style="color:#888;font-size:11px;">
    Generated by mount_monitor.sh on ${HOSTNAME_VAL} at ${TIMESTAMP}
  </p>
</body>
</html>
HTMLEOF
}

#----------------------------------------------------------------------------
# SEND HTML EMAIL via sendmail
#----------------------------------------------------------------------------
send_email() {
    SUBJECT="$1"

    if [ ! -x "${SENDMAIL}" ]; then
        echo "WARNING: sendmail not found or not executable at ${SENDMAIL}. Skipping email." >&2
        return 1
    fi

    (
        echo "MIME-Version: 1.0"
        echo "Content-Type: text/html; charset=UTF-8"
        echo "From: ${MAIL_FROM}"
        echo "To: ${MAIL_TO}"
        echo "Subject: ${SUBJECT}"
        echo ""
        cat "${HTML_REPORT}"
    ) | "${SENDMAIL}" -f "${MAIL_FROM}" "${MAIL_TO}"

    if [ $? -ne 0 ]; then
        echo "WARNING: sendmail exited with an error. Check mail logs." >&2
    else
        echo "Alert email sent to ${MAIL_TO}"
    fi
}

#----------------------------------------------------------------------------
# MONITOR MODE
#----------------------------------------------------------------------------
run_monitor() {
    ensure_basedir

    # Verify baseline exists
    if [ ! -f "${BASELINE_FILE}" ]; then
        echo "ERROR: Baseline file not found: ${BASELINE_FILE}" >&2
        echo "       Run '$0 baseline' on a healthy system first." >&2
        exit 1
    fi

    # Capture current mount points
    get_mounts > "${CURRENT_FILE}"
    if [ $? -ne 0 ]; then
        echo "ERROR: Failed to capture current mount points." >&2
        exit 1
    fi

    # Compare: mounts in baseline but NOT current = missing
    MISSING_FILE="${BASE_DIR}/mounts_missing.txt"
    # Compare: mounts in current but NOT baseline = new
    NEW_FILE="${BASE_DIR}/mounts_new.txt"

    comm -23 "${BASELINE_FILE}" "${CURRENT_FILE}" > "${MISSING_FILE}"
    comm -13 "${BASELINE_FILE}" "${CURRENT_FILE}" > "${NEW_FILE}"

    MISSING_COUNT=$(wc -l < "${MISSING_FILE}" | tr -d ' ')
    NEW_COUNT=$(wc -l    < "${NEW_FILE}"      | tr -d ' ')

    if [ "${MISSING_COUNT}" -eq 0 ] && [ "${NEW_COUNT}" -eq 0 ]; then
        echo "OK: No mount point changes detected at ${TIMESTAMP}"
        exit 0
    fi

    # There are differences — build report and send alert
    echo "ALERT: Mount point deviation detected at ${TIMESTAMP}"
    echo "  Missing : ${MISSING_COUNT}"
    echo "  New     : ${NEW_COUNT}"

    build_html "${MISSING_FILE}" "${NEW_FILE}"

    SUBJECT="[MOUNT ALERT] ${HOSTNAME_VAL} - Missing:${MISSING_COUNT} New:${NEW_COUNT} - ${TIMESTAMP}"
    send_email "${SUBJECT}"

    exit 2   # non-zero so cron/SMF can flag this run as alerting
}

#----------------------------------------------------------------------------
# MAIN
#----------------------------------------------------------------------------
case "${MODE}" in
    baseline)
        run_baseline
        ;;
    monitor)
        run_monitor
        ;;
    *)
        echo "Usage: $0 { baseline | monitor }" >&2
        echo ""
        echo "  baseline  -- Capture current mounts as the reference baseline."
        echo "               Run once on a known-healthy system."
        echo "  monitor   -- Compare current mounts against baseline."
        echo "               Schedule via cron or SMF for continuous monitoring."
        exit 1
        ;;
esac

No comments:

Post a Comment