Define what a health script can prove
A useful health-check script gathers reproducible read-only evidence about operating system availability, resource pressure and service state. It should not automatically restart workloads, delete files, flush firewall rules or change permissions. A healthy process does not guarantee that the application works, so host checks should be paired with endpoint or functional checks where appropriate.
Before running a diagnostic bundle, decide which users may run it, where output will be stored and whether hostnames, addresses, paths or log excerpts are confidential. Root access should be optional for common checks rather than universally required.
Start with a minimal read-only Bash baseline
The following example deliberately avoids installing packages or modifying system state:
#!/usr/bin/env bash
set -euo pipefail
printf 'UTC time: '; date -u +%FT%TZ
printf '\nHost uptime:\n'; uptime
printf '\nFilesystems:\n'; df -hT
printf '\nInodes:\n'; df -i
printf '\nMemory:\n'; free -h
printf '\nFailed systemd units:\n'
systemctl --failed --no-pager || true
The final command is allowed to fail so that an expected systemd/privilege limitation does not hide the rest of the report. In a more comprehensive script, trap errors, identify unsupported commands and return machine-readable statuses. If scripts will be used on multiple distributions, test each platform explicitly.
Add service-aware context
For an Apache/PHP-FPM deployment, supplement the host baseline with systemd unit status, the actual listen socket, the application’s loopback health URL and a safe method check on the PHP endpoint. Do not assume that a running apache2 unit proves the PHP backend is executing.
For Docker-hosted services, inspect container health and recent metadata, but avoid dumping unrestricted environment variables or unredacted logs. For PostgreSQL, use read-only views and a restricted monitoring account rather than embedding database credentials in scripts.
Choose sensible thresholds and explain caveats
A percentage of disk usage alone misses inode exhaustion and filesystem mount conditions. Available memory and load average must be interpreted relative to workload and CPU count. A service state of active cannot tell you whether an application dependency is healthy. Prefer a small set of signals with explicitly documented limitations over a long, noisy report.
Make the script output suitable for a runbook: record UTC timestamp, host identifier if authorized, command version, result, unit and interpretation. Offer JSON output only after defining a stable schema and regression tests.
Validate and distribute safely
Shellcheck and bash -n can help detect obvious script problems; neither replaces testing on isolated representative hosts. Review commands before adding them to a downloadable bundle. Keep any future automated repair actions in separate, approval-gated scripts.