侧边栏壁纸
博主头像
数据渔港

点亮对生活的好奇心

  • 累计撰写 41 篇文章
  • 累计创建 74 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

Linux 常用脚本教程

数据渔港
2026-05-05 / 0 评论 / 0 点赞 / 8 阅读 / 7,395 字
温馨提示:
本文最后更新于 2026-05-05,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

Linux 常用脚本教程

在 VPS 或云服务器上搭建网站,脚本化操作不仅能提高效率,还能保证一致性和可重复性。本文将全面介绍 Linux 环境下各阶段所需的 Bash 脚本、Ansible 自动化、CI/CD 脚本等,从服务器初始化、安全加固、软件安装、网站部署到运维监控,覆盖网站全生命周期管理。


📑 目录

序号章节核心内容
1服务器初始化脚本时区、系统更新、用户创建、SSH 配置
2安全加固脚本UFW 防火墙、Fail2ban、SSH 加固
3环境安装脚本LAMP/LEMP、Node.js/PM2
4网站自动化部署脚本Git 部署、Ansible 剧本
5SSL 证书自动续期Certbot + Crontab 定时续期
6备份与恢复脚本数据库备份、文件同步
7日志管理与切割logrotate 日志轮转
8监控与告警脚本磁盘告警、服务状态检查
9定时任务示例Crontab 实战配置
10常见优化建议错误处理、参数化、权限控制
11Docker 容器部署一键构建运行容器
12Kubernetes 部署kubectl 滚动更新
13性能优化脚本内核调优、Nginx 性能优化
14高级监控脚本容器资源监控、网络连接监控
15自动化测试脚本单元测试、API 测试、负载测试
16灾难恢复脚本数据库+文件一键恢复
17多服务器管理批量 SSH 操作多节点
18证书管理脚本多格式证书生成与分发
19零停机部署蓝绿部署策略
20自动化安全扫描Lynis + ClamAV + Nikto
21网络调试命令ss/netstat/tcpdump/mtr

1. 服务器初始化脚本

首次购买 VPS 后的第一步:更新系统、设置时区、创建新用户并配置 SSH 公钥登录、关闭 root 直连。

#!/usr/bin/env bash
# server_init.sh — 服务器初始化

set -euo pipefail

# 1. 设置时区
timedatectl set-timezone Asia/Shanghai
echo "✅ 时区已设置为 Asia/Shanghai"

# 2. 更新系统
apt update && apt -y upgrade          # Debian/Ubuntu
# yum update -y                        # RHEL/CentOS
echo "✅ 系统已更新"

# 3. 安装基本工具
apt install -y vim wget curl git ufw
echo "✅ 基本工具已安装"

# 4. 创建新用户
read -p "请输入新用户名: " USERNAME
groupadd sudo
useradd -m -s /bin/bash -G sudo $USERNAME
echo "✅ 用户 $USERNAME 已创建"

# 5. 配置 SSH 公钥登录
mkdir -p /home/$USERNAME/.ssh
read -p "请输入公钥内容: " PUBKEY
echo $PUBKEY > /home/$USERNAME/.ssh/authorized_keys
chmod 700 /home/$USERNAME/.ssh
chmod 600 /home/$USERNAME/.ssh/authorized_keys
chown -R $USERNAME:$USERNAME /home/$USERNAME/.ssh
echo "✅ SSH 公钥已配置"

# 6. 禁用 root 密码登录
sed -i 's/^PermitRootLogin .*/PermitRootLogin no/' /etc/ssh/sshd_config
systemctl restart sshd
echo "✅ root 密码登录已禁用"

echo ""
echo "🎉 初始化完成!用户 $USERNAME 已创建并配置 SSH 登录。"

💡 此脚本完成了基础环境准备,接下来可在同一脚本中添加防火墙规则。


2. 安全加固脚本

安全加固主要包含防火墙(UFW/iptables)Fail2banSSH 限制等。

#!/usr/bin/env bash
# security_hardening.sh — 安全加固

set -euo pipefail

# 1. 配置 UFW 防火墙
ufw default deny incoming
ufw default allow outgoing
ufw allow 22/tcp    # SSH
ufw allow 80/tcp    # HTTP
ufw allow 443/tcp   # HTTPS
ufw --force enable
echo "✅ UFW 防火墙已启用"

# 2. 安装并配置 Fail2ban
apt install -y fail2ban
cat > /etc/fail2ban/jail.local <<'EOF'
[sshd]
enabled = true
port = 22
filter = sshd
action = iptables[name=SSH, port=22, protocol=tcp]
logpath = /var/log/auth.log
maxretry = 5
bantime = 3600
findtime = 600
EOF
systemctl enable --now fail2ban
systemctl restart fail2ban
echo "✅ Fail2ban 已配置(5 次失败封禁 1 小时)"

# 3. 修改 SSH 默认端口
NEW_PORT=2222
sed -i "s/#Port 22/Port $NEW_PORT/" /etc/ssh/sshd_config
ufw allow $NEW_PORT/tcp
systemctl restart sshd
echo "✅ SSH 端口已修改为 $NEW_PORT"

echo ""
echo "🔒 安全加固完成!请手动验证 SSH 新端口是否可正常连接。"

安全加固检查清单

项目说明状态
UFW 防火墙仅开放必要端口
Fail2ban防暴力破解
SSH 端口修改降低被扫描风险
Root 禁止密码登录强制密钥认证

3. 环境安装脚本

3.1 LAMP 环境(Linux + Apache + MariaDB + PHP)

#!/usr/bin/env bash
# install_lamp.sh — LAMP 环境一键安装

set -euo pipefail

apt update

# 安装 Apache, MariaDB, PHP
apt install -y apache2 mariadb-server php \
  php-mysql libapache2-mod-php \
  php-curl php-gd php-mbstring php-xml php-zip

# 启动并开机自启
systemctl enable --now apache2 mariadb

# 初始化数据库安全(自动设置 root 密码)
mysql_secure_installation <<EOF
Y
root_password
root_password
Y
Y
Y
Y
EOF

# 测试 PHP
cat > /var/www/html/info.php <<'PHPEOF'
<?php phpinfo(); ?>
PHPEOF

echo ""
echo "🎉 LAMP 环境安装完成!"
echo "   访问 http://$(curl -s ifconfig.me)/info.php 查看 PHP 信息"

LEMP 环境(Nginx + MariaDB + PHP-FPM)

#!/usr/bin/env bash
# install_lemp.sh — LEMP 环境一键安装

set -euo pipefail

apt update
apt install -y nginx mariadb-server php-fpm php-mysql \
  php-curl php-gd php-mbstring php-xml php-zip

# 启动并开机自启
systemctl enable --now nginx mariadb php*-fpm

# 配置 Nginx 站点
cat > /etc/nginx/sites-available/default <<'NGINXEOF'
server {
    listen 80 default_server;
    server_name _;
    root /var/www/html;
    index index.php index.html;

    location / {
        try_files $uri $uri/ =404;
    }

    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/var/run/php/php*-fpm.sock;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
    }
}
NGINXEOF

nginx -t && systemctl reload nginx

echo ""
echo "🎉 LEMP 环境安装完成!请将网站文件放入 /var/www/html"

3.2 Node.js & PM2 环境

#!/usr/bin/env bash
# install_node_pm2.sh — Node.js + PM2 环境

set -euo pipefail

apt update

# 安装 Node.js LTS (20.x)
curl -fsSL https://deb.nodesource.com/setup_20.x | bash -
apt install -y nodejs

# 验证版本
echo "Node.js 版本: $(node -v)"
echo "npm 版本: $(npm -v)"

# 安装 PM2 进程管理器
npm install -g pm2

# 配置 PM2 开机自启
pm2 startup systemd -u $(whoami) --hp $(eval echo ~$(whoami)) >> /tmp/pm2_startup.log 2>&1 || true
env PATH=$PATH:/usr/bin pm2 save

echo ""
echo "🎉 Node.js & PM2 环境配置完成!"
echo "   使用 'pm2 start app.js --name my-app' 启动应用"
echo "   使用 'pm2 status' 查看进程状态"

4. 网站自动化部署脚本

4.1 Git 部署脚本

简单的拉取代码 → 安装依赖 → 重启服务流程:

#!/usr/bin/env bash
# deploy.sh — Git 自动化部署

set -euo pipefail

APP_DIR=/var/www/html/your-app
BRANCH=main
LOG_FILE="/var/log/deploy_$(date +%Y%m%d_%H%M%S).log"

exec > >(tee "$LOG_FILE") 2>&1

echo "========================================="
echo "  开始部署 — $(date '+%Y-%m-%d %H:%M:%S')"
echo "========================================="

cd $APP_DIR

# 1. 拉取最新代码
echo "[1/4] 拉取最新代码..."
git fetch origin
git reset --hard origin/$BRANCH

# 2. 依赖安装 & 构建
echo "[2/4] 安装依赖..."
if [ -f package.json ]; then
    npm ci --production=false && npm run build
elif [ -f composer.json ]; then
    composer install --no-dev --optimize-autoloader
elif [ -f requirements.txt ]; then
    pip install -r requirements.txt
fi

# 3. 数据库迁移(可选)
echo "[3/4] 数据库迁移..."
if [ -f artisan ]; then
    php artisan migrate --force
fi

# 4. 重启服务
echo "[4/4] 重启服务..."
pm2 restart my-app 2>/dev/null || true        # Node.js 服务
systemctl restart php*-fpm 2>/dev/null || true # PHP-FPM
systemctl reload nginx 2>/dev/null || true     # Nginx

echo ""
echo "✅ 部署完成!分支 $BRANCH 的最新代码已上线"
echo "   日志文件: $LOG_FILE"

4.2 Ansible 自动化剧本

Ansible 剧本将多台服务器统一管理,可定义安装、配置、部署流程。

# site.yml — Ansible 主剧本
---
- hosts: webservers
  become: yes
  vars:
    app_repo: 'git@github.com:your/repo.git'
    app_path: '/var/www/html/your-app'
    domain: 'example.com'

  tasks:
    - name: 更新 apt 缓存
      apt: update_cache=yes cache_valid_time=86400

    - name: 安装必要软件
      apt:
        name:
          - nginx
          - git
          - php-fpm
          - nodejs
          - npm
        state: present

    - name: 拉取应用代码
      git:
        repo: '{{ app_repo }}'
        dest: '{{ app_path }}'
        version: 'main'
        force: yes

    - name: 安装 Node.js 依赖
      npm:
        path: '{{ app_path }}'
        production: false

    - name: 构建前端资源
      command: npm run build
      args:
        chdir: '{{ app_path }}'

    - name: 配置 Nginx 站点
      template:
        src: templates/nginx.conf.j2
        dest: /etc/nginx/sites-available/{{ domain }}
      notify: reload nginx

    - name: 启用站点
      file:
        src: /etc/nginx/sites-available/{{ domain }}
        dest: /etc/nginx/sites-enabled/{{ domain }}
        state: link

    - name: 启动 PM2 应用
      command: pm2 restart all
      args:
        chdir: '{{ app_path }}'

  handlers:
    - name: reload nginx
      service: name=nginx state=reloaded
# 使用方式:
ansible-playbook -i inventory site.yml

5. SSL 证书自动续期脚本

使用 Certbot 获取并续期 Let's Encrypt 免费证书。

#!/usr/bin/env bash
# ssl_renew.sh — SSL 证书自动续期

set -euo pipefail

DOMAIN="example.com"
EMAIL="admin@example.com"

echo "开始证书续期 — $(date '+%Y-%m-%d %H:%M:%S')"

# 1. 停止 Nginx(释放 80 端口给 standalone)
systemctl stop nginx

# 2. 获取或续期证书
certbot certonly --standalone \
  -d $DOMAIN -d www.$DOMAIN \
  -m $EMAIL --agree-tos --non-interactive

# 3. 合并证书(可选,用于某些场景)
CERT_DIR="/etc/letsencrypt/live/$DOMAIN"
cat "$CERT_DIR/fullchain.pem" "$CERT_DIR/privkey.pem" \
  > "/etc/nginx/ssl/${DOMAIN}.pem"

# 4. 启动 Nginx
systemctl start nginx

echo "✅ 证书续期完成!时间: $(date '+%F %T')"
# 添加到 Crontab(每 60 天凌晨 3 点执行):
0 3 */60 * * /path/to/ssl_renew.sh >> /var/log/ssl_renew.log 2>&1

6. 备份与恢复脚本

6.1 数据库自动备份

#!/usr/bin/env bash
# db_backup.sh — MySQL/MariaDB 自动备份

set -euo pipefail

DB_USER=root
DB_PASS=your_password
DB_NAME=your_db
BACKUP_ROOT=/backup/mysql
DATE=$(date +"%F")
BACKUP_DIR="$BACKUP_ROOT/$DATE"
RETENTION_DAYS=7

mkdir -p $BACKUP_DIR

# 执行备份(带压缩)
mysqldump -u$DB_USER -p$DB_PASS \
  --single-transaction \
  --routines \
  --triggers \
  $DB_NAME | gzip > "$BACKUP_DIR/${DB_NAME}_$(date +"%H%M").sql.gz"

echo "✅ 数据库备份完成: $BACKUP_DIR"

# 清理过期备份
find $BACKUP_ROOT -type f -mtime +$RETENTION_DAYS -exec rm {} \;

# 可选:同步到远程服务器
# rsync -az --delete $BACKUP_DIR user@backup-server:/remote/backup/mysql/

echo "🗂️ 过期备份已清理(保留最近 $RETENTION_DAYS 天)"

6.2 文件同步备份

#!/usr/bin/env bash
# file_backup.sh — 文件增量同步备份

set -euo pipefail

SOURCE_DIR=/var/www/html
DEST_USER=backup
DEST_HOST=backup.example.com
DEST_DIR=/remote/backup/www
LOG_FILE="/var/log/file_backup_$(date +%Y%m%d).log"

rsync -avz \
  --delete \
  --exclude='node_modules/' \
  --exclude='.git/' \
  --exclude='*.log' \
  --progress \
  $SOURCE_DIR $DEST_USER@$DEST_HOST:$DEST_DIR \
  | tee "$LOG_FILE"

echo "✅ 文件同步完成: $SOURCE_DIR -> $DEST_HOST:$DEST_DIR"

7. 日志管理与日志切割脚本

使用 logrotate 管理日志,防止磁盘空间耗尽。

# /etc/logrotate.d/nginx — Nginx 日志轮转配置
/var/log/nginx/*.log {
    daily              # 每天轮转
    rotate 14          # 保留 14 个历史文件
    missingok          # 文件不存在不报错
    compress           # 压缩旧日志
    delaycompress      # 延迟压缩(当前一个不解压)
    notifempty         # 空文件不轮转
    create 0640 www-data adm
    sharedscripts
    postrotate
        systemctl reload nginx > /dev/null
    endscript
}
# 自定义应用日志轮转示例
# /etc/logrotate.d/myapp
/var/log/myapp/*.log {
    daily
    rotate 30
    compress
    delaycompress
    missingok
    notifempty
    create 0644 www-data www-data
    postrotate
        # 发送信号让应用重新打开日志文件
        kill -USR1 $(cat /var/run/myapp.pid 2>/dev/null) 2>/dev/null || true
    endscript
}

⚠️ 对于自定义日志,在 /etc/logrotate.d/ 中添加对应配置文件即可生效。可用 logrotate -df /etc/logrotate.d/myapp 测试配置。


8. 监控与告警脚本

8.1 磁盘使用率监控

#!/usr/bin/env bash
# disk_alert.sh — 磁盘使用率告警

THRESHOLD=80
ALERT_EMAIL="admin@example.com"

df -H | grep -vE '^Filesystem|tmpfs|cdrom' \
  | awk '{ print $5 " " $1 }' \
  | while read output; do
    usep=$(echo $output | awk '{ print $1}' | sed 's/%//')
    partition=$(echo $output | awk '{ print $2 }')

    if [ $usep -ge $THRESHOLD ]; then
      echo "⚠️ Warning: Partition $partition usage is at ${usep}%!" \
        | mail -s "🚨 Disk Alert: ${usep}% used on $partition" $ALERT_EMAIL
    fi
done

8.2 服务状态检查

#!/usr/bin/env bash
# service_check.sh — 关键服务健康检查

ALERT_EMAIL="admin@example.com"
SERVICES=(nginx mariadb php*-fpm pm2)

for SERVICE in "${SERVICES[@]}"; do
  if ! systemctl is-active --quiet $SERVICE; then
    echo "❌ 服务 $SERVICE 已停止于 $(date '+%Y-%m-%d %H:%M:%S')" \
      | mail -s "🚨 Service Down: $SERVICE" $ALERT_EMAIL
    # 尝试自动重启
    systemctl restart $SERVICE 2>/dev/null || true
  else
    echo "✅ $SERVICE: running"
  fi
done

🔔 将以上脚本放入 Cron 定时执行即可实现基础告警。


9. 定时任务(Crontab)示例

# 编辑 crontab: crontab -e
# 格式: 分 时 日 月 周  命令

# ──── 系统维护 ────
0  2 * * *   /usr/bin/apt update && /usr/bin/apt -y upgrade       # 每日凌晨 2 点系统更新
0  3 * * 0   /usr/bin/apt autoremove -y                           # 每周日凌晨 3 点清理无用包

# ──── 监控告警 ────
0  * * * *   /path/to/disk_alert.sh                               # 每小时磁盘检查
*/15 * * * * /path/to/service_check.sh                            # 每 15 分钟服务检查

# ──── 备份任务 ────
0  1 * * *   /path/to/db_backup.sh                                # 每日 1 点数据库备份
30 2 * * *   /path/to/file_backup.sh                              # 每日 2:30 文件同步

# ──── 证书 & 部署 ────
30 3 */60 * * /path/to/ssl_renew.sh                               # 每 60 天续期证书
0  4 * * 1-5 /path/to/deploy.sh                                   # 工作日早上 4 点自动部署

Cron 快速参考表

字段取值范围说明
0-59分钟
0-23小时
1-31日期
1-12月份
0-7星期(0 和 7 都代表周日)

10. 常见脚本优化建议

建议说明示例
错误处理关键命令后加 || exit 1set -eset -euo pipefail
日志输出统一输出到日志文件exec >> /var/log/script.log 2>&1
参数化可变参数提取为变量或命令行传入./deploy.sh --branch main --env prod
注释文档包含用途说明、参数说明及运行示例脚本头部写清楚用途和用法
权限控制谨慎使用 sudo,文件权限建议 700chmod 700 deploy.sh
幂等性脚本可重复执行且结果一致先判断再操作,避免重复安装
回滚机制部署失败时能快速回退保留上一版本的备份

11. Docker 容器部署脚本

#!/usr/bin/env bash
# deploy_docker.sh — Docker 容器一键部署

set -euo pipefail

IMAGE_NAME=your-app
CONTAINER_NAME=your-app-container
HOST_PORT=80
CONTAINER_PORT=8000
VOLUME_MOUNT="/host/path:/container/path"

echo "========================================="
echo "  Docker 容器部署 — $(date)"
echo "========================================="

# 1. 停止并删除旧容器
docker rm -f $CONTAINER_NAME 2>/dev/null || true

# 2. 清理悬空镜像
docker image prune -f 2>/dev/null || true

# 3. 构建新镜像
docker build -t $IMAGE_NAME .

# 4. 运行容器
docker run -d \
  --name $CONTAINER_NAME \
  --restart=unless-stopped \
  -p $HOST_PORT:$CONTAINER_PORT \
  -v $VOLUME_MOUNT \
  --env-file .env \
  --memory="512m" \
  --cpus="1.0" \
  $IMAGE_NAME

# 5. 健康检查
sleep 3
echo ""
echo "📊 容器状态:"
docker ps -f name=$CONTAINER_NAME --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"

echo ""
echo "📋 最近日志:"
docker logs --tail 20 $CONTAINER_NAME

echo ""
echo "🎉 Docker 容器部署完成!访问 http://$(hostname -I | awk '{print $1}'):$HOST_PORT"

12. Kubernetes 部署脚本

#!/usr/bin/env bash
# deploy_k8s.sh — K8s 滚动更新部署

set -euo pipefail

NAMESPACE=production
DEPLOYMENT=web-app

echo "========================================="
echo "  Kubernetes 部署 — $(date)"
echo "========================================="

# 1. 应用配置
kubectl apply -f k8s/namespace.yaml
kubectl apply -f k8s/configmap.yaml
kubectl apply -f k8s/secrets.yaml
kubectl apply -f k8s/deployment.yaml --namespace=$NAMESPACE
kubectl apply -f k8s/service.yaml --namespace=$NAMESPACE

# 2. 滚动更新
kubectl rollout restart deployment/$DEPLOYMENT --namespace=$NAMESPACE

# 3. 监控更新状态(超时 300 秒)
kubectl rollout status deployment/$DEPLOYMENT \
  --namespace=$NAMESPACE \
  --timeout=300s

# 4. 输出状态信息
echo ""
echo "🌐 Service 信息:"
kubectl get svc -n $NAMESPACE -l app=$DEPLOYMENT

echo ""
echo "📦 Pod 状态:"
kubectl get pods -n $NAMESPACE -l app=$DEPLOYMENT \
  --sort-by='.status.containerStatuses[0].restartCount'

echo ""
echo "🎉 Kubernetes 部署完成!"

13. 性能优化脚本

13.1 内核参数优化

#!/usr/bin/env bash
# tune_kernel.sh — Linux 内核性能调优

set -euo pipefail

# 备份当前配置
cp /etc/sysctl.conf /etc/sysctl.conf.bak_$(date +%F)

cat <<EOF | tee -a /etc/sysctl.conf

# ========== 网络性能优化 ==========
net.core.somaxconn = 65535
net.core.netdev_max_backlog = 4096
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_fin_timeout = 30
net.ipv4.tcp_max_syn_backlog = 4096
net.ipv4.tcp_syncookies = 1
net.ipv4.ip_local_port_range = 1024 65535

# ========== 内存优化 ==========
vm.swappiness = 10
vm.overcommit_memory = 1
vm.dirty_ratio = 10
vm.dirty_background_ratio = 5

# ========== 文件系统优化 ==========
fs.file-max = 2097152
fs.inotify.max_user_watches = 524288
EOF

# 应用配置
sysctl -p

echo "✅ 内核参数优化完成!"

13.2 Nginx 性能调优

#!/usr/bin/env bash
# tune_nginx.sh — Nginx 性能优化

set -euo pipefail

NGINX_CONF="/etc/nginx/nginx.conf"

# 备份原始配置
cp $NGINX_CONF "${NGINX_CONF}.bak_$(date +%F)"

# Worker 进程数设为 CPU 核心数
sed -i '/worker_processes/c\worker_processes auto;' $NGINX_CONF

# Events 区块优化
sed -i '/events {/a\    worker_connections 4096;\n    use epoll;\n    multi_accept on;' $NGINX_CONF

# HTTP 区块追加 TCP 优化
cat <<EOF >> $NGINX_CONF

    # TCP 优化
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 65;
    keepalive_requests 10000;
    sendfile on;

    # 上传限制
    client_max_body_size 100m;
    client_body_buffer_size 128k;
    client_header_buffer_size 4k;
    large_client_header_buffers 4 16k;

    # Gzip 压缩
    gzip on;
    gzip_vary on;
    gzip_proxied any;
    gzip_comp_level 6;
    gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript image/svg+xml;
EOF

# 测试并重载配置
nginx -t && systemctl reload nginx

echo "✅ Nginx 性能优化完成!"

14. 高级监控脚本

14.1 Docker 容器资源监控

#!/usr/bin/env bash
# container_monitor.sh — 容器资源使用监控

set -euo pipefail

ALERT_CPU=80.0
ALERT_MEM="1GiB"
ALERT_EMAIL="admin@example.com"
REPORT_FILE="/tmp/docker_stats_$(date +%Y%m%d_%H%M).txt"

# 收集所有容器资源数据
docker stats --no-stream \
  --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.MemPerc}}\t{{.NetIO}}\t{{.BlockIO}}" \
  > "$REPORT_FILE"

echo "📊 容器资源报告:"
cat "$REPORT_FILE"

# 检查异常容器(CPU 或内存超标)
ALERT_CONTAINERS=$(awk -v cpu="$ALERT_CPU" -v mem="$ALERT_MEM" '
  NR>1 && ($2+0 > cpu || $3 ~ mem) {print $1}' "$REPORT_FILE")

if [ -n "$ALERT_CONTAINERS" ]; then
  echo "" | mail -s "🚨 容器资源告警 — $(date)" $ALERT_EMAIL < "$REPORT_FILE"
  echo "⚠️ 已发送告警邮件!"
else
  echo "✅ 所有容器资源使用正常"
fi

14.2 网络连接监控

#!/usr/bin/env bash
# network_monitor.sh — 异常网络连接检测

set -euo pipefail

SYN_THRESHOLD=100
ALERT_EMAIL="admin@example.com"

echo "🌐 网络连接监控报告 — $(date)"
echo ""

# Top 10 高频连接 IP
echo "=== Top 10 连接 IP ==="
ABNORMAL_CONNS=$(ss -antp state established \
  | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -nr | head -10)
echo "$ABNORMAL_CONNS"

# SYN Flood 攻击检测
SYN_COUNT=$(netstat -n -p tcp 2>/dev/null | grep SYN_RECV | wc -l)
echo ""
echo "=== SYN_RECV 连接数: $SYN_COUNT ==="

if [ $SYN_COUNT -gt $SYN_THRESHOLD ]; then
  echo "🚨 检测到可能的 SYN Flood 攻击! SYN_RECV: $SYN_COUNT" \
    | mail -s "🚨 网络攻击告警 — SYN Flood" $ALERT_EMAIL
fi

# 连接总数统计
echo ""
echo "=== 连接统计摘要 ==="
ss -s | head -10

15. 自动化测试脚本

#!/usr/bin/env bash
# run_tests.sh — 全栈测试套件

set -euo pipefail

APP_URL="http://localhost:8000"
TEST_REPORT="/reports/test_$(date +%Y%m%d_%H%M).html"
mkdir -p /reports

echo "========================================="
echo "  自动化测试套件 — $(date)"
echo "========================================="

# 1. 单元测试
echo ""
echo "[1/4] 运行单元测试..."
pytest tests/unit_tests -v --html=$TEST_REPORT --self-contained-html || true

# 2. API 接口测试
echo ""
echo "[2/4] 运行 API 测试..."
newman run tests/api_tests.postman_collection.json \
  --env-var "baseUrl=$APP_URL" \
  --reporter-html-export reports/api_report.html || true

# 3. 负载测试
echo ""
echo "[3/4] 运行负载测试..."
k6 run tests/load_test.js --summary export=reports/k6_summary.json || true

# 4. 安全扫描
echo ""
echo "[4/4] 运行安全扫描..."
zap-cli quick-scan -s all $APP_URL || true

echo ""
echo "🎉 测试套件执行完成!"
echo "   报告目录: /reports/"

16. 灾难恢复脚本

#!/usr/bin/env bash
# disaster_recovery.sh — 一键灾难恢复

set -euo pipefail

BACKUP_BASE=/backups
LOG_FILE="/var/log/disaster_recovery_$(date +%Y%m%d_%H%M%S).log"

exec > >(tee "$LOG_FILE") 2>&1

echo "========================================="
echo "  ⚠️  灾难恢复程序 — $(date)"
echo "========================================="
echo ""
read -p "确认要执行恢复操作吗?(yes/no): " CONFIRM
[ "$CONFIRM" != "yes" ] && echo "已取消" && exit 0

# 1. 恢复数据库
echo "[1/5] 恢复数据库..."
mysql -u root -p < $BACKUP_BASE/db/latest_full.sql

# 2. 恢复网站文件
echo "[2/5] 恢复网站文件..."
rsync -avz $BACKUP_BASE/files/latest/ /var/www/html/
chown -R www-data:www-data /var/www/html

# 3. 恢复配置文件
echo "[3/5] 恢复配置..."
cp $BACKUP_BASE/configs/nginx.conf /etc/nginx/nginx.conf
cp $BACKUP_BASE/configs/my.cnf /etc/mysql/my.cnf

# 4. 重启所有服务
echo "[4/5] 重启服务..."
systemctl restart mysql nginx php*-fpm

# 5. 验证恢复结果
echo "[5/5] 验证服务状态..."
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" http://localhost)
if [ "$HTTP_CODE" == "200" ]; then
  echo "✅ 服务已恢复正常 (HTTP $HTTP_CODE)"
else
  echo "❌ 服务可能未完全恢复 (HTTP $HTTP_CODE),请手动检查"
fi

echo ""
echo "🔄 灾难恢复完成!日志: $LOG_FILE"

17. 多服务器管理脚本

#!/usr/bin/env bash
# multi_server_ops.sh — 多服务器批量操作

set -euo pipefail

SERVERS=("web1.example.com" "web2.example.com" "db.example.com")
ADMIN_USER="opsadmin"
SSH_KEY="$HOME/.ssh/id_rsa"
LOG_DIR="/var/log/server_ops"
mkdir -p $LOG_DIR

echo "========================================="
echo "  多服务器批量操作 — $(date)"
echo "========================================="

for server in "${SERVERS[@]}"; do
  LOG_FILE="$LOG_DIR/${server}_$(date +%Y%m%d_%H%M).log"

  echo ""
  echo "===== 🖥️  操作服务器: $server ====="

  # 安全更新
  echo "[1/3] 执行安全更新..."
  ssh -i $SSH_KEY $ADMIN_USER@$server \
    "sudo apt update && sudo apt upgrade -y" | tee "$LOG_FILE"

  # 检查磁盘空间
  echo "[2/3] 检查磁盘空间..."
  ssh -i $SSH_KEY $ADMIN_USER@$server "df -h /" | tee -a "$LOG_FILE"

  # 重启关键服务
  echo "[3/3] 重启服务..."
  ssh -i $SSH_KEY $ADMIN_USER@$server \
    "sudo systemctl restart nginx mysql php*-fpm && sudo systemctl status nginx mysql --no-pager" \
    | tee -a "$LOG_FILE"

  echo "===== $server 完成 ====="
done

echo ""
echo "🎉 所有服务器操作完成!日志目录: $LOG_DIR"

18. 证书管理脚本

#!/usr/bin/env bash
# cert_manager.sh — 多格式证书管理与分发

set -euo pipefail

DOMAIN="example.com"
EMAIL="admin@example.com"
CERT_DIR="/etc/letsencrypt/live/$DOMAIN"

echo "========================================="
echo "  证书管理 — $(date)"
echo "========================================="

# 1. 申请/续期证书
echo "[1/4] 申请/续期证书..."
certbot certonly --nginx \
  -d $DOMAIN -d www.$DOMAIN \
  --non-interactive --agree-tos -m $EMAIL

# 2. 生成 PFX 格式(Windows/IIS 用)
echo "[2/4] 生成 PFX 证书..."
openssl pkcs12 -export \
  -out "$CERT_DIR/cert.pfx" \
  -inkey "$CERT_DIR/privkey.pem" \
  -in "$CERT_DIR/cert.pem" \
  -certfile "$CERT_DIR/fullchain.pem" \
  -passout pass:

# 3. 生成 HAProxy 合并证书
echo "[3/4] 生成 HAProxy 证书..."
cat "$CERT_DIR/fullchain.pem" "$CERT_DIR/privkey.pem" \
  > "/etc/haproxy/certs/${DOMAIN}.pem"

# 4. 重载相关服务
echo "[4/4] 重载服务..."
systemctl reload nginx haproxy 2>/dev/null || true

echo ""
echo "✅ 证书管理操作完成!"
echo "   PEM 证书: $CERT_DIR/"
echo "   PFX 证书: $CERT_DIR/cert.pfx"
echo "   HAProxy:  /etc/haproxy/certs/${DOMAIN}.pem"

19. 零停机部署脚本

#!/usr/bin/env bash
# zero_downtime_deploy.sh — 蓝绿部署实现零停机

set -euo pipefail

BLUE_PORT=8080
GREEN_PORT=8081
PROXY_PORT=80

echo "========================================="
echo "  零停机部署(蓝绿策略)— $(date)"
echo "========================================="

# 判断当前活跃环境
CURRENT_COLOR=$(curl -s http://localhost/color 2>/dev/null || echo "none")
echo "当前活跃环境: $CURRENT_COLOR"

if [ "$CURRENT_COLOR" == "blue" ]; then
  TARGET_COLOR="green"; TARGET_PORT=$GREEN_PORT; OLD_PORT=$BLUE_PORT
else
  TARGET_COLOR="blue";  TARGET_PORT=$BLUE_PORT;  OLD_PORT=$GREEN_PORT
fi

echo "目标部署环境: $TARGET_COLOR (端口: $TARGET_PORT)"

# 1. 部署新版本到目标环境
echo "[1/4] 部署新版本到 $TARGET_COLOR 环境..."
docker stop app-$TARGET_COLOR 2>/dev/null || true
docker rm app-$TARGET_COLOR 2>/dev/null || true
docker run -d --name app-$TARGET_COLOR -p $TARGET_PORT:8000 your-app:new-version

# 2. 等待新实例就绪
echo "[2/4] 等待新实例就绪..."
RETRIES=0
while ! nc -z localhost $TARGET_PORT; do
  sleep 2
  RETRIES=$((RETRIES + 1))
  if [ $RETRIES -gt 30 ]; then
    echo "❌ 新实例启动超时!" && exit 1
  fi
done
echo "✅ 新实例已就绪"

# 3. 切换流量(通过 HAProxy/Nginx upstream)
echo "[3/4] 切换流量到 $TARGET_COLOR ..."
# HAProxy 示例:
sed -i "s/default_backend.*/default_backend app-${TARGET_COLOR}/" /etc/haproxy/haproxy.cfg
systemctl reload haproxy

# 4. 停止旧实例
echo "[4/4] 停止旧环境..."
OLD_COLOR=$([ "$TARGET_COLOR" == "green" ] && echo "blue" || echo "green")
docker stop app-$OLD_COLOR 2>/dev/null || true
docker rm app-$OLD_COLOR 2>/dev/null || true

echo ""
echo "🎉 零停机部署完成!当前运行版本: $TARGET_COLOR"

蓝绿部署架构图

                    ┌──────────────┐
                    │   用户请求     │
                    └──────┬───────┘
                           │ :80
                    ┌──────▼───────┐
                    │  HAProxy /   │
                    │  Nginx 反向代理│
                    └──┬────────┬──┘
                       │        │
                  :8080│        │:8081
            ┌────────▼──┐  ┌───▼────────┐
            │  Blue 环境  │  │ Green 环境  │
            │ (当前版本)  │  │ (新版本)    │
            └────────────┘  └────────────┘

20. 自动化安全扫描脚本

#!/usr/bin/env bash
# security_scan.sh — 全方位安全扫描

set -euo pipefail

SCAN_DIR="/var/www/html"
REPORT_DIR="/reports/security/$(date +%Y%m%d_%H%M%S)"
mkdir -p $REPORT_DIR

echo "========================================="
echo "  🔒 安全扫描 — $(date)"
echo "========================================="

# 1. Lynis 系统审计
echo "[1/5] Lynis 系统审计..."
lynis audit system --cronjob > "$REPORT_DIR/lynis.log" 2>&1 || true

# 2. ClamAV 病毒扫描
echo "[2/5] ClamAV 病毒扫描..."
freshclam --quiet
clamscan -r -i $SCAN_DIR > "$REPORT_DIR/clamav.log" 2>&1 || true

# 3. Rkhunter 后门检测
echo "[3/5] Rkhunter 后门检测..."
rkhunter --check --sk > "$REPORT_DIR/rkhunter.log" 2>&1 || true

# 4. Web 漏洞扫描
echo "[4/5] Web 漏洞扫描 (Nikto)..."
nikto -h localhost -output "$REPORT_DIR/nikto.html" 2>&1 || true

# 5. 打包并发送报告
echo "[5/5] 生成报告..."
tar -czf "$REPORT_DIR/security_reports.tar.gz" -C "$REPORT_DIR" . 2>/dev/null || true

echo ""
echo "🔒 安全扫描完成!"
echo "   报告目录: $REPORT_DIR"
echo "   报告归档: $REPORT_DIR/security_reports.tar.gz"

21. 常用网络调试命令

命令说明示例
ss -tulwn列出所有监听端口查看 TCP/UDP 监听状态
ss -s网络连接摘要统计快速了解连接分布
netstat -anp查看网络连接与进程需安装 net-tools
tcpdump -i eth0 port 80抓包指定端口流量tcpdump -i eth0 port 80 -w http.pcap
traceroute example.com跟踪路由路径排查网络延迟节点
mtr -rw example.com实时路由追踪(更直观)结合 traceroute + ping
iperf3 -s / -c网络带宽测试服务端 -s,客户端 -c server_ip
dig example.comDNS 查询排查 DNS 解析问题
curl -I https://example.comHTTP 响应头检查检查 HTTPS/缓存/Server 信息
nc -zv host port端口连通性测试快速检查某端口是否可达
iftop实时流量监控按 Ctrl+C 退出

💡 最佳实践建议

:::info 最佳实践

  • 执行前备份:运行任何脚本前先创建系统快照或备份重要数据
  • 理解脚本逻辑:不要盲目执行,先阅读代码了解功能和风险
  • 测试环境验证:在生产环境使用前,先在测试机验证兼容性
  • 记录操作日志:使用 script 命令记录执行过程便于排查问题
  • 定期更新维护:关注依赖更新,及时修复已知漏洞和 bug
    :::

❓ 常见问题 FAQ

Q: 如何给脚本添加执行权限?

使用 chmod 命令赋予执行权限:

chmod +x script_name.sh
./script_name.sh

如果遇到权限错误,检查文件所有者并使用 sudo 提权。建议先用 cat script_name.sh 查看内容确认安全性后再执行。

Q: 脚本执行失败如何排查?

排查步骤:

  1. 语法检查bash -n script.sh
  2. 开启调试模式bash -x script.sh(查看详细执行过程)
  3. 检查依赖which command(确认命令是否存在)
  4. 查看系统日志journalctl -xe/var/log/syslog
  5. 确认权限和资源ls -ladf -hfree -h
Q: 如何设置脚本开机自动执行?

三种方法:

方法适用场景推荐度
Systemd Service生产环境推荐⭐⭐⭐⭐⭐
/etc/rc.local简单场景⭐⭐
Cron @reboot定时重启执行⭐⭐⭐

Systemd 方式示例(最推荐):

# /etc/systemd/system/my-script.service
[Unit]
Description=My Startup Script
After=network.target

[Service]
Type=simple
ExecStart=/path/to/script.sh
Restart=on-failure

[Install]
WantedBy=multi-user.target
sudo systemctl enable my-script.service
Q: 如何编写可复用的 Shell 函数库?

将常用功能封装成函数,放入独立文件中:

# functions.sh — 公共函数库
log_info()  { echo "[$(date '+%H:%M:%S')] [INFO]  $*"; }
log_error() { echo "[$(date '+%H:%M:%S')] [ERROR] $*" >&2; }
check_cmd() { command -v "$1" >/dev/null 2>&1; }

confirm() {
  read -p "$1 (yes/no): " ans
  [ "$ans" = "yes" ]
}

# 在其他脚本中使用
source /path/to/functions.sh
log_info "开始执行..."

优点:提高代码复用性和可维护性,统一日志格式和错误处理。


📝 本文持续更新中,如有补充或修正欢迎反馈。

0

评论区

ip); ?>