If you’ve worked with Linux for a while, you already know that a lot of tasks start to feel repetitive, such as checking disk usage, restarting services that fail, or running updates, which can take up a lot of time. It gets even more annoying when you’re managing multiple servers.
This is where Bash scripts come in handy.
Think of Bash scripts as small helpers that do the boring work for you. Instead of typing the same commands again and again, you can write them once and let the script run them whenever you need. This not only saves time but also reduces mistakes that can happen when you do things manually.
Over time, Linux administrators have built many useful scripts to monitor systems, handle routine maintenance, and even catch issues early before they turn into bigger problems.
In this article, we’ll look at five simple and practical Bash scripts that you can use in day-to-day Linux system administration. They are beginner-friendly, easy to understand, and you can easily tweak them to fit your own setup.
1. Disk Usage Monitor Script
One of the most common late-night surprises on any Linux server is running out of disk space, where logs grow, backups accumulate, or a user uploads a large file, and suddenly your application starts failing because /var or another partition is full.
Instead of waiting for things to break, you can automate a simple check that keeps an eye on disk usage and alerts you when something crosses a safe limit.
This script checks all mounted partitions and sends an email alert if any of them go above 80% usage.
#!/bin/bash THRESHOLD=80 EMAIL="[email protected]" df -hP | grep -vE '^Filesystem|tmpfs|devtmpfs|udev' | while read -r line; do USAGE=$(echo "$line" | awk '{print $5}' | sed 's/%//') MOUNTPOINT=$(echo "$line" | awk '{print $6}') if [ "$USAGE" -ge "$THRESHOLD" ]; then echo "Warning: $MOUNTPOINT is at ${USAGE}% on $HOSTNAME" | \ mail -s "Disk Alert: $HOSTNAME" "$EMAIL" fi done
How it works (step by step):
df -hP: shows disk usage for all mounted filesystems in a consistent format (one line per partition).grep -vE '^Filesystem|tmpfs|devtmpfs|udev': removes the header row and virtual filesystems that do not represent real disk storage.awk '{print $5}': extracts the usage percentage column.sed 's/%//': removes the % symbol so we can compare it as a number.[ "$USAGE" -ge "$THRESHOLD" ]: checks if usage is greater than or equal to 80%.
If a partition crosses the limit, the script sends a simple email alert showing which mount point is affected.
To make sure the script runs regularly (say every 6 hours), you can schedule it with cron:
0 */6 * * * /usr/local/bin/disk-monitor.sh
Once this is in place, your server quietly keeps watch for you, and you get notified before disk space becomes a real problem.
2. System Update Automation Script
Keeping packages updated is one of the easiest and most effective security practices on any Linux server, but logging into every machine, running updates manually, and checking the output doesn’t scale well, especially if you manage multiple servers.
This script automates the full update process, logs everything for later review, and sends you a short email summary so you know what changed.
It works on Ubuntu/Debian-based systems and Rocky Linux/RHEL-based systems with a small command difference.
On Ubuntu:
#!/bin/bash LOGFILE="/var/log/sys-updates.log" EMAIL="[email protected]" echo "=== Update started: $(date) ===" >> "$LOGFILE" apt update >> "$LOGFILE" 2>&1 apt upgrade -y >> "$LOGFILE" 2>&1 apt autoremove -y >> "$LOGFILE" 2>&1 echo "=== Update finished: $(date) ===" >> "$LOGFILE" tail -30 "$LOGFILE" | mail -s "Update Report: $HOSTNAME" "$EMAIL"
On RHEL:
#!/bin/bash LOGFILE="/var/log/sys-updates.log" EMAIL="[email protected]" echo "=== Update started: $(date) ===" >> "$LOGFILE" dnf upgrade -y >> "$LOGFILE" 2>&1 dnf autoremove -y >> "$LOGFILE" 2>&1 echo "=== Update finished: $(date) ===" >> "$LOGFILE" tail -30 "$LOGFILE" | mail -s "Update Report: $HOSTNAME" "$EMAIL"
What this script does (in simple terms):
apt update / dnf upgrade: refreshes package lists and installs available updates.> "$LOGFILE" 2>&1: saves both normal output and errors into a log file, so nothing is missed.autoremove: cleans up unused packages that were installed as dependencies.tail -30: sends only the last part of the log in the email so your inbox doesn’t get flooded.
Run it once every day at 2 AM when the system is usually idle:
0 2 * * * /usr/local/bin/auto-update.sh
If email sending doesn’t work, install a mail utility first:
sudo apt install mailutils #Ubuntu sudo dnf install mailx #RHEL
Once this is set up, your servers stay patched automatically, and you still get a quick daily summary without logging in manually.
3. Service Health Checker Script
On any Linux server, services will fail sooner or later. It might be Apache, MySQL, SSH, or something critical to your application. The real problem is not the crash itself, but how long it stays down before you notice it.
This script continuously checks your important services, restarts them if they are down, and sends you an alert so you know exactly what happened.
#!/bin/bash
SERVICES=("apache2" "mysql" "ssh")
EMAIL="[email protected]"
for SERVICE in "${SERVICES[@]}"; do
if ! systemctl is-active --quiet "$SERVICE"; then
systemctl start "$SERVICE"
STATUS=$?
if [ $STATUS -eq 0 ]; then
echo "$SERVICE was down and has been restarted on $HOSTNAME" | \
mail -s "Service Restarted: $SERVICE on $HOSTNAME" "$EMAIL"
else
echo "$SERVICE failed to restart on $HOSTNAME. Manual intervention needed." | \
mail -s "Service FAILED to Restart: $SERVICE on $HOSTNAME" "$EMAIL"
fi
fi
done
How it works (simple explanation):
systemctl is-active --quiet "$SERVICE": checks if the service is running.- Exit code 0 means it is running
- Any other value means it is down
--quietkeeps the output clean
systemctl start "$SERVICE": tries to bring the service back up if it is down.$?: captures whether the restart succeeded or failed.- First
if: detects a service failure. - Second
if: checks whether the restart worked or not and sends the appropriate alert.
On RHEL-based distributions, the Apache service name is different:
apache2 → httpd
So your service list should look like this:
SERVICES=("httpd" "mysql" "ssh")
To make sure you catch issues quickly, run it every 5 minutes:
*/5 * * * * /usr/local/bin/service-checker.sh
Once this is in place, your server starts acting like it has basic self-healing. If something goes down, it tries to recover immediately and notifies you at the same time.
4. Backup Script for Important Files
Backups are one of those things every Linux admin knows they should set up, but often delay until something actually breaks, and by then, it’s usually too late.
This simple script helps you avoid that situation. It automatically creates a compressed backup of your important directories, checks whether it worked, sends you a status email, and also cleans up old backups so your storage doesn’t slowly fill up.
#!/bin/bash BACKUP_DIR="/backup" SOURCE_DIRS="/etc /var/www /home" DATE=$(date +%F) BACKUP_FILE="$BACKUP_DIR/backup-$DATE.tar.gz" EMAIL="[email protected]" RETENTION_DAYS=7 mkdir -p "$BACKUP_DIR" tar -czf "$BACKUP_FILE" $SOURCE_DIRS 2>/dev/null EXIT_CODE=$? if [ $EXIT_CODE -eq 0 ]; then SIZE=$(du -sh "$BACKUP_FILE" | awk '{print $1}') echo "Backup completed: $BACKUP_FILE ($SIZE)" | \ mail -s "Backup Success: $HOSTNAME" "$EMAIL" else echo "Backup FAILED on $HOSTNAME. Exit code: $EXIT_CODE" | \ mail -s "Backup FAILED: $HOSTNAME" "$EMAIL" fi find "$BACKUP_DIR" -name "backup-*.tar.gz" -mtime +$RETENTION_DAYS -delete
How it works (in simple terms):
mkdir -p "$BACKUP_DIR": creates the backup folder if it doesn’t exist yet.tar -czf: compresses your important directories into a single .tar.gz file.2>/dev/null: hides harmless warnings (like special system files in /proc).EXIT_CODE=$?: checks whether the backup command succeeded.du -sh: shows the final size of the backup so you can quickly verify it looks normal.find ... -mtime +$RETENTION_DAYS -delete: removes backups older than 7 days to save space.
Run it every night at 1 AM when system usage is low:
0 1 * * * /usr/local/bin/backup.sh
Once this is in place, your system quietly protects itself in the background, and you always have a recent copy ready if something goes wrong.
5. User Login Monitoring Script
On a production Linux server, knowing who logs in is just as important as knowing what services are running. Especially for SSH access, unexpected logins can be an early sign of misconfiguration or even a security issue.
This script keeps track of new login sessions and sends you an email only when something new happens, so you don’t have to constantly stare at logs.
Ubuntu typically writes authentication logs to /var/log/auth.log, so we can monitor that file directly.
#!/bin/bash LOGFILE="/var/log/auth.log" LAST_RUN_FILE="/tmp/login_monitor_last_run" EMAIL="[email protected]" NOW=$(date +%s) if [ ! -f "$LAST_RUN_FILE" ]; then date -d '5 minutes ago' +%s > "$LAST_RUN_FILE" fi LAST_RUN=$(cat "$LAST_RUN_FILE") LOGINS=$(awk '/session opened for user/ { cmd = "date -d \""$1" "$2" "$3" $(date +%Y)\" +%s 2>/dev/null" cmd | getline t close(cmd) if (t+0 >= '"$LAST_RUN"'+0 && t+0 <= '"$NOW"'+0) print $0 }' "$LOGFILE") if [ -n "$LOGINS" ]; then echo "$LOGINS" | mail -s "Login Activity: $HOSTNAME" "$EMAIL" fi echo "$NOW" > "$LAST_RUN_FILE"
On RHEL-systems, it relies on systemd-journald, so we query logs using journalctl.
#!/bin/bash LAST_RUN_FILE="/tmp/login_monitor_last_run" EMAIL="[email protected]" NOW=$(date +%s) if [ ! -f "$LAST_RUN_FILE" ]; then date -d '5 minutes ago' +%s > "$LAST_RUN_FILE" fi LAST_RUN=$(cat "$LAST_RUN_FILE") SINCE=$(date -d @"$LAST_RUN" '+%Y-%m-%d %H:%M:%S') LOGINS=$(journalctl _SYSTEMD_UNIT=sshd.service --since "$SINCE" --no-pager | \ grep "session opened for user") if [ -n "$LOGINS" ]; then echo "$LOGINS" | mail -s "Login Activity: $HOSTNAME" "$EMAIL" fi echo "$NOW" > "$LAST_RUN_FILE"
How it works (simple explanation):
LAST_RUN_FILE: stores the last time the script ran so it only checks new logins.session opened for user: the log message generated when a user successfully logs in.journalctl _SYSTEMD_UNIT=sshd.service: reads SSH login events on systems that use systemd logs instead of/var/log/auth.log.if [ -n "$LOGINS" ]: ensures you only get an email when there is actual login activity.
Run it every 5 minutes for near real-time visibility:
*/5 * * * * /usr/local/bin/login-monitor.sh
With this in place, your server quietly reports every new login, giving you a simple but powerful security layer without constant manual checking.
Conclusion
These five scripts are not complicated, but they solve the exact problems you run into on real Linux servers. A disk that slowly fills up, a service that crashes in the middle of the night, systems that go unpatched for weeks, backups that are never actually tested, and logins that nobody notices until it is too late.
Each script is small enough that you can understand it in a couple of minutes and adjust it in a few more to match your own environment. That is the real strength of Bash automation: simple building blocks that quietly handle repetitive work for you.
If you are just starting out, begin with the disk usage monitor and the service health checker. Set them up, plug in your email, and schedule them with cron. With just those two in place, you already cover two of the most common causes of 3 AM server alerts.
From there, you can gradually add backups, update automation, and login monitoring as you get more comfortable. So the question is simple: which of these are already running in your setup, and what would you add next?
If you want to take this further, the next step is building a full system health check that combines CPU, memory, disk, and service status into a single daily report. That is covered in: How to Automate Daily Linux Health Checks with a Bash Script + Cron.






It’s often difficult to read stories on the site, because the Table of Contents popout actually blocks your content behind it. Please provide a way to turn it off or at least close it temporarily.
@Clay,
Hey, sorry about that, that’s not the experience we want.
The TOC is meant to help with long articles, not get in the way of reading them.
Could you share which browser and device you’re on, and if possible a quick screenshot of what you’re seeing? That’ll help us pinpoint whether it’s a specific screen size or browser rendering issue and get it fixed properly.
Same here (TOC overlap content), but enlarging browser (firefox) window solve the problem, on the other hand if you make window smaller, TOC disappear (problem also).
@Jean,
Thanks for reporting this. You were right, and I’ve fixed it.
The TOC was positioned on the left side of the screen, which caused it to overlap the article content on smaller browser windows. I’ve moved it to the bottom-right corner where it stays out of the reading area at any window size.
Give it a try and let me know if you still see any issues.
Service health checker script is not correct; it is the same as the backup script for…
@jean,
Sorry about that. I’ve updated the script now and corrected the issue.
Use a external monitor, like check_mk or zabbix.
In Fedora 20 I have 0.7.0 in repository ;)