Memory/CPU Snapshot Report (Bash)¶
Generate a quick system health snapshot and write it to a dated report file. Use it to debug slowdowns, check resource usage, or keep lightweight audit logs.
What it captures¶
- Host, timestamp, uptime, kernel
- CPU load average and optional CPU model summary (
lscpu) - Memory usage (
free -h) - Swap and VM stats (
vmstat) - Top processes by CPU and by memory (RSS) with full commands for memory hogs
- Disk usage (
df -hT) - Network summary (
ss -s) - Optional Docker snapshot (
docker ps,docker stats --no-stream)
Requirements¶
Most Linux systems already have these:
- bash
- ps (procps)
- free (procps)
- vmstat (procps)
- df (coreutils)
- ss (iproute2) optional but recommended
- lscpu (util-linux) optional
- docker optional for container snapshot
Install missing packages (Debian/Ubuntu):
sudo apt update
sudo apt install -y procps iproute2 util-linux coreutils
Usage¶
1) Save the script below as memcpu-snapshot.sh.
2) Make it executable: chmod +x memcpu-snapshot.sh.
3) Run it: ./memcpu-snapshot.sh (for example: ./memcpu-snapshot.sh -n 25 -o /var/log/snapshots -p serverA).
4) Reports default to ./reports/ with names like snapshot_<HOST>_YYYY-MM-DD_HH-MM-SS.txt.
Options¶
| Option | Meaning | Default |
|---|---|---|
-n, --top N |
Number of top processes to show | 15 |
-o, --out DIR |
Output directory for reports | ./reports |
-p, --prefix NAME |
Report filename prefix | snapshot |
-h, --help |
Show usage | n/a |
Automation (cron)¶
Example: run every 30 minutes and write to /var/log/snapshots:
*/30 * * * * /path/to/memcpu-snapshot.sh -o /var/log/snapshots -n 20 >/dev/null 2>&1
Ensure the output directory exists and is writable:
sudo mkdir -p /var/log/snapshots
sudo chown -R "$USER":"$USER" /var/log/snapshots
Script¶
#!/usr/bin/env bash
set -euo pipefail
# Memory/CPU Snapshot Report
# - Outputs system snapshot + top processes
# - Saves to a dated report file
TOP_N=15
OUT_DIR="./reports"
PREFIX="snapshot"
usage() {
cat <<'EOF'
Usage:
./memcpu-snapshot.sh [options]
Options:
-n, --top N Number of top processes to include (default: 15)
-o, --out DIR Output directory for reports (default: ./reports)
-p, --prefix NAME Report filename prefix (default: snapshot)
-h, --help Show this help
Examples:
./memcpu-snapshot.sh
./memcpu-snapshot.sh -n 25
./memcpu-snapshot.sh -o /var/log/snapshots -p serverA
EOF
}
# Parse args
while [[ $# -gt 0 ]]; do
case "${1}" in
-n|--top)
TOP_N="${2:-}"
shift 2
;;
-o|--out)
OUT_DIR="${2:-}"
shift 2
;;
-p|--prefix)
PREFIX="${2:-}"
shift 2
;;
-h|--help)
usage
exit 0
;;
*)
echo "Unknown option: ${1}"
echo
usage
exit 1
;;
esac
done
# Validate TOP_N is a positive integer
if ! [[ "$TOP_N" =~ ^[0-9]+$ ]] || [[ "$TOP_N" -lt 1 ]]; then
echo "Error: --top must be a positive integer (got: $TOP_N)" >&2
exit 1
fi
mkdir -p "$OUT_DIR"
HOST="$(hostname -s 2>/dev/null || hostname)"
TS="$(date '+%Y-%m-%d_%H-%M-%S')"
REPORT="${OUT_DIR}/${PREFIX}_${HOST}_${TS}.txt"
# Helpers
hr() { printf '%*s\n' 90 '' | tr ' ' '-'; }
section() { hr; echo "# $1"; hr; }
{
section "Snapshot Metadata"
echo "Host : $HOST"
echo "Timestamp : $(date -R)"
echo "User : $(whoami)"
echo "Uptime : $(uptime -p 2>/dev/null || uptime)"
echo "Kernel : $(uname -srmo 2>/dev/null || uname -a)"
echo
section "CPU / Load"
echo "Load average: $(awk '{print $1,$2,$3}' /proc/loadavg 2>/dev/null || echo 'N/A')"
if command -v lscpu >/dev/null 2>&1; then
echo
echo "lscpu (summary):"
lscpu | awk -F: '
$1 ~ /(Model name|CPU\(s\)|Thread|Core|Socket|MHz|Architecture)/ {
gsub(/^[ \t]+/, "", $2); printf " %-20s %s\n", $1 ":", $2
}'
else
echo "lscpu not installed (skipping CPU model details)."
fi
echo
section "Memory (free -h)"
if command -v free >/dev/null 2>&1; then
free -h
else
echo "free not installed (try: sudo apt install procps)."
fi
echo
section "Swap / VM Stats (vmstat)"
if command -v vmstat >/dev/null 2>&1; then
vmstat -S M 1 2
else
echo "vmstat not installed (try: sudo apt install procps)."
fi
echo
section "Top Processes by CPU (top ${TOP_N})"
ps -eo pid,ppid,user,stat,ni,pri,pcpu,pmem,rss,etime,comm \
--sort=-pcpu | head -n $((TOP_N + 1))
echo
section "Top Processes by Memory RSS (top ${TOP_N})"
ps -eo pid,ppid,user,stat,ni,pri,pcpu,pmem,rss,etime,comm \
--sort=-rss | head -n $((TOP_N + 1))
echo
section "Memory Hog Details (RSS + full command)"
ps -eo pid,rss,pmem,pcpu,etime,args --sort=-rss | head -n $((TOP_N + 1))
echo
section "Disk Usage (df -h)"
df -hT 2>/dev/null || df -h
echo
section "Network (ss -s)"
if command -v ss >/dev/null 2>&1; then
ss -s
else
echo "ss not installed (try: sudo apt install iproute2)."
fi
echo
section "Docker (optional)"
if command -v docker >/dev/null 2>&1; then
echo "docker ps (running):"
docker ps --format 'table {{.Names}}\t{{.Status}}\t{{.Image}}' 2>/dev/null || true
echo
echo "docker stats (single snapshot):"
docker stats --no-stream 2>/dev/null || true
else
echo "Docker not installed (skipping)."
fi
echo
section "End of Report"
echo "Saved to: $REPORT"
} | tee "$REPORT" >/dev/null
echo "Report saved: $REPORT"