#!/usr/bin/env bash set -o errexit set -o nounset set -o pipefail include_system=0 usage() { cat <<'USAGE' Usage: check_filesystem_readonly.sh [--include-system] [--help] Detect filesystems mounted read-only. Read-only. USAGE } while (($# > 0)); do case "$1" in --include-system) include_system=1; shift ;; --help|-h) usage; exit 0 ;; *) printf 'CRITICAL: unknown option: %s\n' "$1"; usage; exit 2 ;; esac done tmp_mounts="$(mktemp)" trap 'rm -f "$tmp_mounts"' EXIT if command -v findmnt >/dev/null 2>&1; then findmnt -rn -o TARGET,SOURCE,FSTYPE,OPTIONS > "$tmp_mounts" 2>/dev/null || true elif command -v mount >/dev/null 2>&1; then mount | awk '{ source=$1; target=$3; type=$5; opts=$6; gsub(/[()]/, "", opts); print target, source, type, opts }' > "$tmp_mounts" else printf 'CRITICAL: findmnt or mount is required\n' exit 2 fi tmp_ro="$(mktemp)" trap 'rm -f "$tmp_mounts" "$tmp_ro"' EXIT awk -v include_system="$include_system" ' function system_fs(type, target) { return type ~ /^(proc|sysfs|tmpfs|devtmpfs|devpts|securityfs|cgroup|cgroup2|pstore|bpf|tracefs|debugfs|configfs|fusectl|mqueue|hugetlbfs|overlay|squashfs|autofs)$/ || target ~ /^\/(proc|sys|dev|run)(\/|$)/ } { target=$1; source=$2; type=$3; opts=$4 if (opts ~ /(^|,)ro(,|$)/) { if (include_system == 1 || ! system_fs(type, target)) { print target "\t" source "\t" type "\t" opts } } } ' "$tmp_mounts" > "$tmp_ro" readonly_count="$(wc -l < "$tmp_ro" | awk '{print $1}')" status="OK" exit_code=0 if ((readonly_count > 0)); then status="CRITICAL" exit_code=3 fi printf '%s: Found %s read-only filesystem(s)\n\n' "$status" "$readonly_count" printf 'Read-only filesystems:\n' if [[ -s "$tmp_ro" ]]; then printf 'MOUNT_POINT\tSOURCE\tFSTYPE\tOPTIONS\n' cat "$tmp_ro" else printf 'OK: no read-only filesystems found with current filters\n' fi printf '\n' printf 'Evidence:\n' printf 'include_system=%s\n' "$include_system" printf 'Collector: ' if command -v findmnt >/dev/null 2>&1; then printf 'findmnt\n' else printf 'mount fallback\n' fi printf '\n' printf 'Recommended next steps:\n' printf -- '- Check dmesg or journal logs for I/O errors and filesystem remount events\n' printf -- '- Check storage path, multipath, SAN, cloud volume, or underlying disk health\n' printf -- '- Check filesystem health with the platform-approved procedure\n' printf -- '- Do not remount read-write before understanding the cause\n' printf -- '- Attach this output to incident ticket\n' exit "$exit_code"