90 lines
2.5 KiB
Bash
90 lines
2.5 KiB
Bash
|
|
#!/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"
|