Operations 15 min read

Essential Bash Scripts for Linux Server Setup, Monitoring, and Maintenance

This article provides a collection of ready‑to‑run Bash scripts that cover disk partition creation, server initialization, real‑time network traffic monitoring, Nginx log rotation and analysis, disk usage alerts, MySQL backups, process counting with zombie termination, and automated blocking of malicious IPs, offering a practical toolkit for Linux system administrators.

Liangxu Linux
Liangxu Linux
Liangxu Linux
Essential Bash Scripts for Linux Server Setup, Monitoring, and Maintenance

1. Disk Partition Creation

This script creates a primary partition on a specified disk, supports ext4 or xfs filesystems, and prompts the user for the device path, partition number, start sector, and size. It uses fdisk to create the partition, formats it, updates /etc/fstab, runs partprobe, and mounts the new filesystem.

#! /bin/bash
# Function:对硬盘进行分区,得到一个标准的linux文件系统(ext4/xfs)的主分区
cat /proc/partitions > old
read -p "请输入你要分区的硬盘(写绝对路径,如:/dev/sda):" A
if [ -e $A ]; then
  echo "true"
else
  echo "该设备不存在!!"
  exit
fi
read -p "请输入你要创建的磁盘分区类型(这里只能是主分区,默认按回车即可):" B
read -p "请输入分区数字,范围1-4,默认从1开始,默认按回车即可:" C
read -p "请输入扇区起始表号,默认按回车即可:" D
read -p "请输入你要分区的分区大小(格式:如 +5G ):" E
fdisk $A << EOF
n
p
$C
$D
$E
w
EOF
echo "一个标准的linux文件系统的分区已经建立好!!"
partprobe $A
echo "-------------------------------"
cat /proc/partitions
cat /proc/partitions > new
F=`diff new old | grep "<" | awk '{print $5}'`
echo "-------------------------------"
echo $F
echo "你想对新分区设定什么类型的文件系统?有以下选项:"
echo "A:ext4文件系统"
echo "B:xfs文件系统"
read -p "请输入你的选择:" G
case $G in
        a|A)
           mkfs.ext4 /dev/$F
           echo "该分区将被挂载在 "/mnt/$F" 下"
           m=`ls /mnt/|grep $F | wc -l`
           if [ $m -eq 0 ]; then
            mkdir /mnt/$F
           fi
           n=`cat /etc/fstab | grep /dev/$F| wc -l`
           if [ $n -eq 0 ]; then
              echo "/dev/$F      /mnt/$F      ext4         defaults          0      0" >> /etc/fstab
           else
              sed -i '/^\/dev\/$F/c\/dev/$F      /mnt/$F      ext4         defaults          0      0' /etc/fstab
           fi
           mount -a
           df -Th
        ;;
        b|B)
           mkfs.xfs -f /dev/$F
           echo "该分区将被挂载在 "/mnt/$F" 下"
           m=`ls /mnt/|grep $F | wc -l`
           if [ $m -eq 0 ]; then
              mkdir /mnt/$F
           fi
           n=`cat /etc/fstab | grep /dev/$F | wc -l`
           if [ $n -eq 0 ]; then
              echo "/dev/$F      /mnt/$F      xfs         defaults          0      0" >> /etc/fstab
           else
              sed -i '/^\/dev\/$F/c\/dev/$F      /mnt/$F      xfs         defaults          0      0' /etc/fstab
           fi
           mount -a
           df -Th
        ;;
        *)
           echo "你的输入有误!!"
        esac

2. Server Initialization

This script configures basic server settings: sets the timezone to Asia/Shanghai, adds an NTP sync cron job, disables SELinux, stops and disables the firewall (systemd firewalld for RHEL 7, iptables for RHEL 6), enables command‑history timestamps, sets an SSH idle timeout, disables root remote login, disables mail notifications for cron, raises the maximum number of open files, applies kernel sysctl tweaks for TCP performance, reduces swap usage, and installs common performance tools.

#/bin/bash
# 设置时区并同步时间
ln -s /usr/share/zoneinfo/Asia/Shanghai /etc/localtime
if ! crontab -l |grep ntpdate &>/dev/null ; then
    (echo "* 1 * * * ntpdate time.windows.com >/dev/null 2>&1";crontab -l) |crontab
fi
# 禁用selinux
sed -i '/SELINUX/{s/permissive/disabled/}' /etc/selinux/config
# 关闭防火墙
if egrep "7.[0-9]" /etc/redhat-release &>/dev/null; then
    systemctl stop firewalld
    systemctl disable firewalld
elif egrep "6.[0-9]" /etc/redhat-release &>/dev/null; then
    service iptables stop
    chkconfig iptables off
fi
# 历史命令显示操作时间
if ! grep HISTTIMEFORMAT /etc/bashrc; then
    echo 'export HISTTIMEFORMAT="%F %T `whoami` "' >> /etc/bashrc
fi
# SSH超时时间
if ! grep "TMOUT=600" /etc/profile &>/dev/null; then
    echo "export TMOUT=600" >> /etc/profile
fi
# 禁止root远程登录
sed -i 's/#PermitRootLogin yes/PermitRootLogin no/' /etc/ssh/sshd_config
# 禁止定时任务向发送邮件
sed -i 's/^MAILTO=root/MAILTO=""/' /etc/crontab
# 设置最大打开文件数
if ! grep "* soft nofile 65535" /etc/security/limits.conf &>/dev/null; then
    cat >> /etc/security/limits.conf << EOF
* soft nofile 65535
* hard nofile 65535
EOF
fi
# 系统内核优化
cat >> /etc/sysctl.conf << EOF
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_max_tw_buckets = 20480
net.ipv4.tcp_max_syn_backlog = 20480
net.core.netdev_max_backlog = 262144
net.ipv4.tcp_fin_timeout = 20
EOF
# 减少SWAP使用
echo "0" > /proc/sys/vm/swappiness
# 安装系统性能分析工具及其他
yum install gcc make autoconf vim sysstat net-tools iostat -y

3. Real‑time Network Interface Traffic

The script accepts a network interface name as the first argument and prints inbound and outbound bandwidth (KB/s) every second by reading /proc/net/dev.

#!/bin/bash
NIC=$1
echo -e " In ------ Out"
while true; do
    OLD_IN=$(awk '$0~"'$NIC'"{print $2}' /proc/net/dev)
    OLD_OUT=$(awk '$0~"'$NIC'"{print $10}' /proc/net/dev)
    sleep 1
    NEW_IN=$(awk '$0~"'$NIC'"{print $2}' /proc/net/dev)
    NEW_OUT=$(awk '$0~"'$NIC'"{print $10}' /proc/net/dev)
    IN=$(printf "%.1f%s" "$((($NEW_IN-$OLD_IN)/1024))" "KB/s")
    OUT=$(printf "%.1f%s" "$((($NEW_OUT-$OLD_OUT)/1024))" "KB/s")
    echo "$IN $OUT"
    sleep 1
done

4. Nginx Log Daily Rotation

This script moves yesterday’s access log into a month‑based directory and sends a USR1 signal to nginx so it reopens its log files.

#!/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 /usr/local/nginx/nginx.pid)

5. Nginx Access Log Analysis

The script analyses an nginx access log (passed as the first argument) to list the top 10 IPs by request count, the most active IPs within a specific time window, the most requested pages (only those with more than 10 hits), and status‑code statistics, using awk and sort.

#!/bin/bash
# 日志格式: $remote_addr - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" "$http_x_forwarded_for"
LOG_FILE=$1
echo "统计访问最多的10个IP"
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 "统计时间段访问最多的IP"
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 "统计访问最多的10个页面"
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 "统计访问页面状态码数量"
awk '{a[$7" "$9]++}END{for(v in a){if(a[v]>5) print v,a[v]}}' $LOG_FILE

6. Disk Utilization Monitoring

This script reads a host list file ( host.info) where each line contains IP, username, and SSH port, SSHes to each host, runs df -h, extracts partition names and usage percentages, and prints a warning when usage exceeds 80 %.

#!/bin/bash
HOST_INFO=host.info  # 主机列表,实现采集多台主机信息,需要能够ssh到目标主机
for IP in $(awk '/^[^#]/{print $1}' $HOST_INFO); do
    USER=$(awk -v ip=$IP 'ip==$1{print $2}' $HOST_INFO)
    PORT=$(awk -v ip=$IP 'ip==$1{print $3}' $HOST_INFO)
    TMP_FILE=/tmp/disk.tmp
    ssh -p $PORT $USER@$IP 'df -h' > $TMP_FILE
    USE_RATE_LIST=$(awk 'BEGIN{OFS="="}/^\/dev/{print $NF,int($5)}' $TMP_FILE)
    for USE_RATE in $USE_RATE_LIST; do
        PART_NAME=${USE_RATE%=*}
        USE_RATE=${USE_RATE#*=}
        if [ $USE_RATE -ge 80 ]; then
            echo "Warning: $PART_NAME Partition usage $USE_RATE%!"
        fi
    done
done

7. MySQL Backup

The script obtains a list of non‑system databases from a local MySQL server, creates a timestamped directory for each database, dumps every table with mysqldump, and reports any dump failures.

#!/bin/bash
DATE=$(date +%F_%H-%M-%S)
HOST=localhost
USER=backup
PASS=passwd
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 备份失败!"
        fi
    done
done

8. Process Counting and Zombie Killing

This script enumerates processes from /proc, counts how many are running, stopped, sleeping, or zombies, writes zombie PIDs to a file, and kills them.

#!/bin/bash
ALL_PROCESS=$(ls /proc/ | egrep "[0-9]+")
running_count=0
stoped_count=0
sleeping_count=0
zombie_count=0
for pid in ${ALL_PROCESS[*]}; do
    test -f /proc/$pid/status && state=$(egrep "state" /proc/$pid/status | awk '{print $2}')
    case "$state" in
        R) running_count=$((running_count+1)) ;;
        T) stoped_count=$((stoped_count+1)) ;;
        S) sleeping_count=$((sleeping_count+1)) ;;
        Z) zombie_count=$((zombie_count+1)) ; echo "$pid" >> zombie.txt ; kill -9 $pid ;;
    esac
done
echo -e "total:
$((running_count+stoped_count+sleeping_count+zombie_count))
running:$running_count
stoped:$stoped_count
sleeping:$sleeping_count
zombie:$zombie_count"

9. Blocking Malicious IPs

The script extracts recent IP addresses from the nginx access log that have made more than ten requests within the current minute, checks whether each IP already has an iptables DROP rule, adds the rule if missing, and logs the action with a timestamp.

#!/bin/bash
DATE=$(date +%d/%b/%Y:%H:%M)
LOG_FILE=/usr/local/nginx/logs/access.log
ABNORMAL_IP=$(tail -n10000 $LOG_FILE |grep $DATE |awk '{a[$1]++}END{for(i in a)if(a[i]>10)print i}')
for IP in $ABNORMAL_IP; do
    if [ $(iptables -vnL |grep -c "$IP") -eq 0 ]; then
        iptables -I INPUT -s $IP -j DROP
        echo "$(date +'%F_%T') $IP" >> /tmp/drop_ip.log
    fi
done
Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

automationNGINXServerBashdisk
Liangxu Linux
Written by

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.)

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.