Essential Bash Scripts for Nginx, MySQL, and Linux System Monitoring
This guide provides a collection of ready‑to‑use Bash scripts for daily Nginx log rotation, log analysis, server resource monitoring, inode warnings, malicious IP blocking, bulk file renaming, scheduled log clearing, Apache process supervision, and both single‑ and multi‑database MySQL backups.
1. Daily Nginx Access Log Rotation
#!/bin/bash
LOG_DIR=/usr/local/nginx/logs
YESTERDAY_TIME=$(date -d "yesterday" +%F)
LOG_MONTH_DIR=$LOG_DIR/$(date +"%Y-%m")
LOG_FILE_LIST="default.access.log"
for LOG_FILE in $LOG_FILE_LIST; do
[ ! -d $LOG_MONTH_DIR ] && mkdir -p $LOG_MONTH_DIR
mv $LOG_DIR/$LOG_FILE $LOG_MONTH_DIR/${LOG_FILE}_${YESTERDAY_TIME}
done
kill -USR1 $(cat /var/run/nginx.pid)2. Nginx Access Log Analysis Script
#!/bin/bash
# Log format: $remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" "$http_x_forwarded_for"
LOG_FILE=$1
echo "Top 10 IPs (UV)"
awk '{a[$1]++} END {print "UV:", length(a); for (v in a) print v, a[v]}' $LOG_FILE | sort -k2 -nr | head -10
echo "----------------------"
echo "Top IPs in a time window"
awk '$4>="[01/Dec/2018:13:20:25" && $4<="[27/Nov/2018:16:20:49" {a[$1]++} END {for (v in a) print v, a[v]}' $LOG_FILE | sort -k2 -nr | head -10
echo "----------------------"
echo "Top 10 requested pages (PV)"
awk '{a[$7]++} END {print "PV:", length(a); for (v in a) if (a[v]>10) print v, a[v]}' $LOG_FILE | sort -k2 -nr
echo "----------------------"
echo "Status code count per page"
awk '{a[$7" "$9]++} END {for (v in a) if (a[v]>5) print v, a[v]}' $LOG_FILE | sort -k3 -nr3. One‑Click Server Resource Utilization Overview
#!/bin/bash
function cpu() {
NUM=1
while [ $NUM -le 3 ]; do
util=$(vmstat | awk '{if(NR==3)print 100-$15"%"}')
iowait=$(vmstat | awk '{if(NR==3)print $16"%"}')
echo "CPU - Usage: $util , IO Wait: $iowait"
let NUM++
sleep 1
done
}
function memory() {
total=$(free -m | awk '{if(NR==2)printf "%.1f", $2/1024}')
used=$(free -m | awk '{if(NR==2)printf "%.1f", ($2-$NF)/1024}')
available=$(free -m | awk '{if(NR==2)printf "%.1f", $NF/1024}')
echo "Memory - Total: ${total}G , Used: ${used}G , Free: ${available}G"
}
function disk() {
fs=$(df -h | awk '/^\/dev/{print $1}')
for p in $fs; do
mounted=$(df -h | awk -v dev="$p" '$1==dev{print $NF}')
size=$(df -h | awk -v dev="$p" '$1==dev{print $2}')
used=$(df -h | awk -v dev="$p" '$1==dev{print $3}')
used_percent=$(df -h | awk -v dev="$p" '$1==dev{print $5}')
echo "Disk - Mount: $mounted , Size: $size , Used: $used , Usage: $used_percent"
done
}
function tcp_status() {
summary=$(ss -antp | awk '{status[$1]++} END {for(i in status) printf i":"status[i]" "}')
echo "TCP connections - $summary"
}
cpu
memory
disk
tcp_status4. Real‑Time Inode Usage Alert
#!/bin/bash
# Alert when free inodes drop below 100
PATH=/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/sbin:/home/wl/bin
export PATH
for FreeInode in $(df -i | grep -v "Filesystem" | awk '{print $4}'); do
if [[ $FreeInode -lt 100 ]]; then
echo -e "$(df -i | grep "$FreeInode")" > /service/script/.FreeInode
mail -s "FreeInode Warning" wl < /service/script/.FreeInode
fi
done5. Block Malicious IPs from Nginx Access Logs
#!/bin/bash
DATE=$(date +%d/%b/%Y:%H:%M)
# Get the last 10000 lines, filter current minute, count per IP, flag >500 requests
ABNORMAL_IP=$(tail -n10000 access.log | grep $DATE | awk '{a[$1]++} END {for(i in a) if(a[i]>500) print i}')
for IP in $ABNORMAL_IP; do
if [ $(iptables -vnL | grep -c "$IP") -eq 0 ]; then
iptables -I INPUT -s $IP -j DROP
fi
done6. Batch Rename File Extensions
#!/bin/bash
# Usage: script.sh old_ext new_ext
for i in `ls *.$1`; do
mv $i ${i%.*}.$2
done7. Scheduled Log Truncation and Size Recording
#!/bin/bash
logfile=/tmp/$(date +%H-%F).log
hour=$(date +%H)
if [ $hour -eq 00 ] || [ $hour -eq 12 ]; then
for i in `find /data/log/ -type f`; do
> $i
done
else
for i in `find /data/log/ -type f`; do
du -sh $i >> $logfile
done
fi8. Apache (httpd) Process Monitoring and Auto‑Restart
#!/bin/bash
check_service() {
j=0
for i in `seq 1 5`; do
/usr/local/apache2/bin/apachectl restart 2>/var/log/httpderr.log
if [ $? -eq 0 ]; then
break
else
j=$((j+1))
fi
if [ $j -eq 5 ]; then
mail.py exit
fi
done
}
while :; do
n=$(pgrep -l httpd | wc -l)
if [ $n -gt 500 ]; then
/usr/local/apache2/bin/apachectl restart
if [ $? -ne 0 ]; then
check_service
else
sleep 60
n2=$(pgrep -l httpd | wc -l)
if [ $n2 -gt 500 ]; then
mail.py exit
fi
fi
fi
sleep 10
done9. Single‑Loop MySQL Database Backup
#!/bin/bash
DATE=$(date +%F_%H-%M-%S)
HOST=localhost
USER=backup
PASS=123.com
BACKUP_DIR=/data/db_backup
DB_LIST=$(mysql -h$HOST -u$USER -p$PASS -s -e "show databases;" 2>/dev/null | egrep -v "Database|information_schema|mysql|performance_schema|sys")
for DB in $DB_LIST; do
BACKUP_NAME=$BACKUP_DIR/${DB}_$DATE.sql
if ! mysqldump -h$HOST -u$USER -p$PASS -B $DB > $BACKUP_NAME 2>/dev/null; then
echo "$BACKUP_NAME backup failed!"
fi
done10. Multi‑Loop MySQL Database Backup (per table)
#!/bin/bash
DATE=$(date +%F_%H-%M-%S)
HOST=localhost
USER=backup
PASS=123.com
BACKUP_DIR=/data/db_backup
DB_LIST=$(mysql -h$HOST -u$USER -p$PASS -s -e "show databases;" 2>/dev/null | egrep -v "Database|information_schema|mysql|performance_schema|sys")
for DB in $DB_LIST; do
BACKUP_DB_DIR=$BACKUP_DIR/${DB}_$DATE
[ ! -d $BACKUP_DB_DIR ] && mkdir -p $BACKUP_DB_DIR >/dev/null
TABLE_LIST=$(mysql -h$HOST -u$USER -p$PASS -s -e "use $DB;show tables;" 2>/dev/null)
for TABLE in $TABLE_LIST; do
BACKUP_NAME=$BACKUP_DB_DIR/${TABLE}.sql
if ! mysqldump -h$HOST -u$USER -p$PASS $DB $TABLE > $BACKUP_NAME 2>/dev/null; then
echo "$BACKUP_NAME backup failed!"
fi
done
doneSigned-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Liangxu Linux
Liangxu, a self‑taught IT professional now working as a Linux development engineer at a Fortune 500 multinational, shares extensive Linux knowledge—fundamentals, applications, tools, plus Git, databases, Raspberry Pi, etc. (Reply “Linux” to receive essential resources.)
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
