Bash Scripts I Reuse on Every New Server
Every server I take over, whether it's a fresh VPS or a box a client has been running for years, gets the same small set of scripts dropped into /usr/local/bin. None of them are clever. They're the kind of thing you'd write in five minutes and forget about, except I've been carrying the same ones, lightly updated, for years, because they keep paying for themselves.
1. The "what does this server look like" snapshot
First thing I run on any server, new or unfamiliar, is a quick snapshot script. It prints disk usage, memory, load average, the top processes by memory, and anything listening on a network port:
#!/bin/bash
# server-snapshot.sh
echo "== Uptime & Load =="
uptime
echo -e "\n== Disk Usage =="
df -hT --total | grep -E '^(Total|/dev)'
echo -e "\n== Memory =="
free -h
echo -e "\n== Top 5 Memory Consumers =="
ps aux --sort=-%mem | head -6
echo -e "\n== Listening Ports =="
ss -tulpn | grep LISTEN
It's nothing you couldn't type manually, but typing five separate commands every time you log into a server you don't fully remember is how things get missed. One script, one glance, and I have a mental model of the box before I touch anything.
2. Finding what's actually eating the disk
"Disk is full" is one of the most common alerts I get, and the cause is almost never where people expect. This one walks down from root, sorts by size, and stops at a sane depth so it doesn't bury you in thousands of lines:
#!/bin/bash
# disk-hogs.sh
du -ahx --max-depth="${1:-3}" / 2>/dev/null | sort -rh | head -25
Run it with no arguments and it checks three levels deep. Pass a number and it goes deeper. Nine times out of ten the answer is logs, an old backup someone forgot about, or a stray node_modules directory that somehow made it onto the server.
3. Checking certificate expiry without a dashboard
Not every site is behind a monitoring stack, especially smaller client setups. For those, a quick loop over a list of domains tells me how many days are left on each certificate:
#!/bin/bash
# cert-check.sh
while read -r domain; do
expiry=$(echo | openssl s_client -servername "$domain" -connect "$domain:443" 2>/dev/null \
| openssl x509 -noout -enddate | cut -d= -f2)
days=$(( ($(date -d "$expiry" +%s) - $(date +%s)) / 86400 ))
printf "%-35s %s days\n" "$domain" "$days"
done < domains.txt
I keep a domains.txt per client with one hostname per line and run this monthly. With Let's Encrypt usually handling renewals automatically, this script's real job is catching the cases where renewal silently failed.
4. Cleaning up logs and journal bloat
systemd's journal and application logs have a way of quietly filling a disk over months. Before I go hunting for a "mystery" disk usage problem, I run this:
#!/bin/bash
# log-cleanup.sh
journalctl --vacuum-time=2weeks
find /var/log -name "*.gz" -mtime +30 -delete
find /var/log -name "*.log.*" -mtime +30 -delete
It's deliberately conservative, two weeks of journal and 30 days of rotated logs is more than enough for almost any debugging session, while keeping the disk from creeping toward full.
Keeping them in one place
All of these live in a small git repo I clone onto every server I manage:
git clone https://github.com/yourname/server-toolkit /opt/toolkit
ln -s /opt/toolkit/*.sh /usr/local/bin/
The scripts themselves aren't the point. The point is that when something looks off at 11pm on a server I haven't logged into in months, I'm not starting from a blank terminal. I'm running the same commands I always run, and that familiarity is worth more than any of them individually.