> 10个超实用Shell脚本:一键搞定服务器运维

为什么我收藏了这些脚本

做运维这些年,我积累了一套"瑞士军刀"级别的Shell脚本。每拿到一台新服务器,第一时间就是把这些脚本部署上去。今天把最实用的10个分享出来。

每个脚本我都在生产环境跑过,可以直接复制使用。

脚本1:服务器初始化

新服务器拿到手,一键完成基础配置:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#!/bin/bash
# init_server.sh - 新服务器初始化脚本

set -e

echo "===== 服务器初始化开始 ====="

# 更新系统
echo "[1/6] 更新系统..."
apt update && apt upgrade -y

# 安装常用工具
echo "[2/6] 安装常用工具..."
apt install -y curl wget git vim htop unzip fail2ban ufw

# 配置时区
echo "[3/6] 配置时区..."
timedatectl set-timezone Asia/Shanghai
echo "当前时间: $(date)"

# 配置防火墙
echo "[4/6] 配置防火墙..."
ufw allow ssh
ufw allow 80/tcp
ufw allow 443/tcp
ufw --force enable

# 配置fail2ban
echo "[5/6] 配置fail2ban..."
systemctl enable fail2ban
systemctl start fail2ban

# 优化系统参数
echo "[6/6] 优化内核参数..."
cat >> /etc/sysctl.conf <<EOF
# 网络优化
net.core.somaxconn = 65535
net.ipv4.tcp_max_tw_buckets = 5000
net.ipv4.tcp_fin_timeout = 30
EOF
sysctl -p

echo "===== 初始化完成 ====="

脚本2:自动备份(MySQL + 文件)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#!/bin/bash
# backup.sh - 每日自动备份脚本

DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_DIR="/backup"
RETENTION_DAYS=7
LOG="/var/log/backup.log"

# MySQL配置
DB_USER="root"
DB_PASS="your_password"

log() {
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a $LOG
}

mkdir -p $BACKUP_DIR/{mysql,files}

# 备份MySQL
log "开始备份MySQL..."
mysqldump -u$DB_USER -p$DB_PASS --all-databases 2>/dev/null | gzip > $BACKUP_DIR/mysql/all_db_$DATE.sql.gz
if [ $? -eq 0 ]; then
    SIZE=$(ls -lh $BACKUP_DIR/mysql/all_db_$DATE.sql.gz | awk '{print $5}')
    log "MySQL备份成功: $SIZE"
else
    log "MySQL备份失败!"
fi

# 备份网站文件
log "开始备份文件..."
tar -czf $BACKUP_DIR/files/www_$DATE.tar.gz /var/www/ 2>/dev/null
if [ $? -eq 0 ]; then
    SIZE=$(ls -lh $BACKUP_DIR/files/www_$DATE.tar.gz | awk '{print $5}')
    log "文件备份成功: $SIZE"
else
    log "文件备份失败!"
fi

# 清理旧备份
log "清理${RETENTION_DAYS}天前的备份..."
find $BACKUP_DIR -name "*.gz" -mtime +$RETENTION_DAYS -delete
REMAINING=$(find $BACKUP_DIR -name "*.gz" | wc -l)
log "当前备份文件数: $REMAINING"

log "备份完成"

运行效果:

1
2
3
4
5
6
7
8
9
$ chmod +x backup.sh
$ ./backup.sh
[2026-02-03 03:00:01] 开始备份MySQL...
[2026-02-03 03:00:15] MySQL备份成功: 23M
[2026-02-03 03:00:15] 开始备份文件...
[2026-02-03 03:00:45] 文件备份成功: 156M
[2026-02-03 03:00:45] 清理7天前的备份...
[2026-02-03 03:00:46] 当前备份文件数: 14
[2026-02-03 03:00:46] 备份完成

脚本3:磁盘空间报警

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
#!/bin/bash
# disk_alert.sh - 磁盘空间监控

THRESHOLD=80
ALERT_EMAIL="[email protected]"

df -h | awk 'NR>1' | while read line; do
    USAGE=$(echo $line | awk '{print $5}' | tr -d '%')
    MOUNT=$(echo $line | awk '{print $6}')
    AVAIL=$(echo $line | awk '{print $4}')

    if [ -n "$USAGE" ] && [ "$USAGE" -gt "$THRESHOLD" ] 2>/dev/null; then
        MSG="警告: $MOUNT 使用率 ${USAGE}%,剩余 $AVAIL"
        echo "$MSG"
        echo "$MSG" | mail -s "磁盘报警 - $(hostname)" $ALERT_EMAIL 2>/dev/null
    fi
done

脚本4:批量SSH执行命令

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
#!/bin/bash
# batch_ssh.sh - 批量在多台服务器执行命令

SERVERS=(
    "[email protected]"
    "[email protected]"
    "[email protected]"
)

CMD="$@"

if [ -z "$CMD" ]; then
    echo "用法: $0 <command>"
    echo "示例: $0 uptime"
    exit 1
fi

for SERVER in "${SERVERS[@]}"; do
    echo "===== $SERVER ====="
    ssh -o ConnectTimeout=5 $SERVER "$CMD" 2>&1
    echo ""
done
1
2
3
4
5
6
7
8
$ ./batch_ssh.sh "uptime && df -h /"
===== [email protected] =====
 10:00:00 up 30 days,  3:22,  1 user,  load average: 0.15, 0.10, 0.08
/dev/vda1        40G   12G   26G  32% /

===== [email protected] =====
 10:00:00 up 45 days,  7:15,  1 user,  load average: 0.52, 0.38, 0.31
/dev/vda1        40G   25G   13G  66% /

脚本5:网站可用性监控

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
#!/bin/bash
# site_monitor.sh - 网站可用性监控

SITES=(
    "https://example.com"
    "https://blog.example.com"
    "https://api.example.com/health"
)
LOG="/var/log/site_monitor.log"

for SITE in "${SITES[@]}"; do
    HTTP_CODE=$(curl -o /dev/null -s -w "%{http_code}" --connect-timeout 10 "$SITE")
    RESPONSE_TIME=$(curl -o /dev/null -s -w "%{time_total}" --connect-timeout 10 "$SITE")

    if [ "$HTTP_CODE" -ne 200 ]; then
        echo "[$(date)] FAIL: $SITE 返回 $HTTP_CODE" | tee -a $LOG
        # 可以在这里加钉钉/微信通知
    else
        echo "[$(date)] OK: $SITE (${RESPONSE_TIME}s)" | tee -a $LOG
    fi
done
Crontab配置频率说明
*/1 * * * *每分钟核心业务
*/5 * * * *每5分钟普通站点
*/15 * * * *每15分钟非关键服务

脚本6:日志切割与清理

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#!/bin/bash
# log_rotate.sh - 日志管理脚本

LOG_DIR="/var/log/myapp"
KEEP_DAYS=30

# 按日期切割当前日志
TODAY=$(date +%Y%m%d)
for log in $LOG_DIR/*.log; do
    if [ -f "$log" ]; then
        mv "$log" "${log}.$TODAY"
        gzip "${log}.$TODAY"
        touch "$log"
    fi
done

# 重载应用使其使用新日志文件
systemctl reload nginx 2>/dev/null

# 删除过期日志
find $LOG_DIR -name "*.gz" -mtime +$KEEP_DAYS -delete

echo "日志切割完成,已清理${KEEP_DAYS}天前的日志"

脚本7:Docker一键部署

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#!/bin/bash
# deploy.sh - Docker应用部署脚本

set -e

APP_DIR="/opt/myapp"
IMAGE_NAME="myapp"
CONTAINER_NAME="myapp-web"

cd $APP_DIR

echo "=== 拉取最新代码 ==="
git pull origin main

echo "=== 构建Docker镜像 ==="
docker build -t $IMAGE_NAME:latest .

echo "=== 停止旧容器 ==="
docker stop $CONTAINER_NAME 2>/dev/null || true
docker rm $CONTAINER_NAME 2>/dev/null || true

echo "=== 启动新容器 ==="
docker run -d \
    --name $CONTAINER_NAME \
    --restart=always \
    -p 3000:3000 \
    -v $APP_DIR/data:/app/data \
    $IMAGE_NAME:latest

echo "=== 清理旧镜像 ==="
docker image prune -f

echo "=== 部署完成 ==="
docker ps | grep $CONTAINER_NAME

脚本8:系统资源报告

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#!/bin/bash
# system_report.sh - 每日系统报告

echo "=============================="
echo "  系统资源报告 - $(date '+%Y-%m-%d')"
echo "  主机: $(hostname)"
echo "=============================="

echo -e "\n[运行时间]"
uptime

echo -e "\n[CPU使用 Top5]"
ps aux --sort=-%cpu | head -6 | awk '{printf "%-10s %-6s %-6s %s\n", $1, $3"%", $4"%", $11}'

echo -e "\n[内存]"
free -h

echo -e "\n[磁盘]"
df -h | grep -E '^/dev/'

echo -e "\n[网络连接统计]"
ss -s | head -4

echo -e "\n[最近登录]"
last -5

echo "=============================="

脚本9:安全审计检查

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#!/bin/bash
# security_check.sh - 安全审计脚本

echo "===== 安全审计报告 ====="
echo "时间: $(date)"

echo -e "\n[1] SSH暴力破解尝试 (Top 10 IP)"
grep "Failed password" /var/log/auth.log 2>/dev/null | \
    awk '{print $(NF-3)}' | sort | uniq -c | sort -rn | head -10

echo -e "\n[2] 当前登录用户"
who

echo -e "\n[3] 有sudo权限的用户"
grep -E '^sudo:' /etc/group | cut -d: -f4

echo -e "\n[4] 监听端口"
ss -tlnp | awk 'NR>1 {print $4, $6}'

echo -e "\n[5] 最近修改的系统文件"
find /etc -mtime -7 -type f 2>/dev/null | head -20

echo -e "\n[6] 防火墙状态"
ufw status 2>/dev/null || iptables -L -n 2>/dev/null | head -10

echo "===== 审计完成 ====="

脚本10:一键安装Docker

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#!/bin/bash
# install_docker.sh - 一键安装Docker和Docker Compose

set -e

echo "===== 安装Docker ====="

# 检查是否已安装
if command -v docker &> /dev/null; then
    echo "Docker已安装: $(docker --version)"
    exit 0
fi

# 安装依赖
apt update
apt install -y ca-certificates curl gnupg

# 添加Docker仓库
install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
chmod a+r /etc/apt/keyrings/docker.gpg

echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \
  https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
  tee /etc/apt/sources.list.d/docker.list > /dev/null

# 安装Docker
apt update
apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

# 启动服务
systemctl enable --now docker

# 验证
docker --version
docker compose version

echo "===== Docker安装完成 ====="

使用建议

脚本建议触发方式Crontab示例
备份脚本每日凌晨0 3 * * *
磁盘报警每小时0 * * * *
网站监控每5分钟*/5 * * * *
日志清理每周0 4 * * 0
系统报告每日早上0 8 * * *
安全审计每周0 9 * * 1

总结

这10个脚本覆盖了运维最常见的场景。建议在服务器上创建一个/root/scripts/目录专门存放这些脚本,配合Crontab定时执行。

Shell脚本基础语法可以参考Shell脚本编程入门。定时任务的详细配置请看Crontab定时任务全攻略

Shell脚本 运维自动化 实用脚本
cd ..