Linux 运维与安全专家 11 · 脚本自动化与批量运维

第 11 章 · 脚本自动化与批量运维

阶段 C预计 6–8 小时从手动到一键

「每次都是搜索或问 AI」的根源是没把重复操作固化成自己的工具。本章让你学会用 Bash 脚本把日常操作自动化,再用 Ansible 把「一台服务器」的管理复制到「一百台」—— 这正是运维从入门到专业的分水岭。

11.1脚本思维:把「你会手动做的事」写下来

一个实用的进阶路径:先手动做一遍成功 → 把命令按顺序写成脚本 → 加判断与日志 → 挂 cron → 多台机器用 Ansible 铺开。你不是在学编程语言,是在「把操作记录成可复用的流程」。

11.2Bash 脚本语法速成(30 分钟够用)

示例 · /usr/local/bin/demo.sh 语法骨架
#!/bin/bash
# 第一行 shebang:指定解释器;bash 脚本必写
set -euo pipefail
# -e 出错即停  -u 未定义变量报错  -o pipefail 管道失败即算失败(专业脚本默认三连)

NAME="webapp"                        # 变量(等号两边不能有空格)
echo "开始部署 $NAME"                # $变量 引用

if [ -f /etc/nginx/nginx.conf ]; then   # 条件:文件存在?([] 两边有空格!)
  echo "nginx 已安装"
else
  echo "nginx 未安装,开始安装"
  sudo apt install -y nginx
fi

for ip in 192.168.1.10 192.168.1.11; do    # 循环
  ping -c1 -W1 $ip >/dev/null && echo "$ip 通" || echo "$ip 不通"
done

check_disk() {                           # 函数
  df -h / | awk 'NR==2 {print $5}'
}
echo "根分区使用率:$(check_disk)"

exit 0                                    # 退出码:0=成功,非 0=失败(供上层判断)
终端 · 运行与调试
chmod +x demo.sh          # 加执行权限
./demo.sh                 # 运行
bash -x demo.sh           # 逐行打印执行过程(调试神器)
bash -n demo.sh           # 只检查语法不执行
echo $?                   # 上一条命令的退出码

11.3三个实战脚本(先抄后改,理解每一行)

脚本 1:数据库每日备份

/usr/local/bin/backup_db.sh
#!/bin/bash
set -euo pipefail
DB=wordpress
BACKUP_DIR=/data/backups
DATE=$(date +%F)
mkdir -p $BACKUP_DIR
mysqldump -u backup --single-transaction $DB | gzip > $BACKUP_DIR/${DB}_${DATE}.sql.gz
find $BACKUP_DIR -name "*.sql.gz" -mtime +30 -delete   # 只留 30 天
echo "[$(date +%F_%T)] 备份完成" >> /var/log/backup.log

脚本 2:新服务器一键初始化(把第 9 章加固写进去)

/usr/local/bin/init_server.sh(片段)
#!/bin/bash
set -euo pipefail
# 1. 更新系统
sudo apt update && sudo apt upgrade -y   # Rocky: dnf update -y
# 2. 装基础工具
sudo apt install -y vim curl wget htop sysstat fail2ban ufw
# 3. 防火墙默认拒绝 + 放行 SSH/Web
sudo ufw default deny incoming
sudo ufw allow 2222/tcp && sudo ufw allow 80,443/tcp
sudo ufw --force enable
# 4. 创建运维账号并加入 sudo
sudo useradd -m -s /bin/bash ops
echo "ops:$(openssl rand -base64 12)" | sudo chpasswd
sudo usermod -aG sudo ops
# 5. 加固 sshd(禁 root、禁密码)
sudo sed -i 's/^PermitRootLogin.*/PermitRootLogin no/' /etc/ssh/sshd_config
sudo sed -i 's/^PasswordAuthentication.*/PasswordAuthentication no/' /etc/ssh/sshd_config
sudo systemctl restart sshd
echo "初始化完成"

脚本 3:服务健康检查 + 自愈

/usr/local/bin/health_check.sh(cron 每 5 分钟)
#!/bin/bash
set -euo pipefail
if ! systemctl is-active --quiet nginx; then
  systemctl start nginx
  echo "$(date) nginx 掉线已拉起" >> /var/log/selfheal.log
  curl -s -X POST "https://oapi.dingtalk.com/robot/send?access_token=XXX" \
    -H 'Content-Type: application/json' \
    -d '{"msgtype":"text","text":{"content":"nginx 自愈重启"}}'
fi

11.4定时与触发:让脚本自己跑

11.5Ansible:一台变一百台(批量运维入门)

Ansible:无代理(走 SSH)、声明式(写「要什么状态」而非「怎么执行」)、幂等(重复执行结果一致)。一条命令给几百台机器装软件、改配置、重启服务。

终端 · 三分钟上手
# 控制机(你的笔记本/跳板机)安装
sudo apt install ansible    # Ubuntu;Rocky: dnf install epel-release && dnf install ansible-core

# 定义受管机器(/etc/ansible/hosts 或项目内 hosts.ini)
# [web]
# 203.0.113.10 ansible_user=ops
# 203.0.113.11 ansible_user=ops

# 连通性测试
ansible web -m ping

# 批量执行命令
ansible web -m shell -a "uptime"
ansible web -m command -a "ss -tlnp | head"

# Playbook:写“目标状态”,示例 /opt/deploy.yml
---
- hosts: web
  become: yes
  tasks:
    - name: 安装 nginx
      apt: name=nginx state=latest
    - name: 拷贝站点配置
      copy: src=./site.conf dest=/etc/nginx/conf.d/site.conf
    - name: 重启 nginx
      systemd: name=nginx state=restarted
# 执行:
ansible-playbook -i hosts.ini deploy.yml
学习节奏 第一周先会 ansible -m ping / -m shell 批量跑命令;再学着把「第 11.3 节的初始化脚本」改写成 playbook;Ansible 本身就是一份完整知识体系,入门后按官方文档进阶(第 16 章有资料清单)。

11.6脚本安全习惯(写脚本的三条红线)

本章自测题

  1. Bash 脚本第一行必须写什么?set -euo pipefail 三个各防什么?
  2. if 判断文件存在、for 循环遍历 IP 的语法各写一遍。
  3. 如何调试脚本(逐行打印)?如何只看语法?
  4. 写一个「每天备份 nginx 配置目录,保留 7 份,删除更旧的」脚本并挂 cron。
  5. Ansible 的三种特点(无代理/声明式/幂等)各是什么意思?
  6. Ansible 批量执行命令用什么模块?批量安装软件写 playbook 的最小例子?
  7. 脚本里为什么不能写死密码?替代方案?
参考答案
1. #!/bin/bash;-e 出错即停、-u 未定义变量报错、-o pipefail 管道失败即失败。
2. if [ -f 文件 ]; then ... fi;for ip in 列表; do ... done。
3. bash -x 脚本.sh;bash -n 脚本.sh。
4. 脚本:cp -a /etc/nginx /data/nginx_backup_$(date +%F) + find ... -mtime +7 -delete;cron:0 2 * * * /usr/local/bin/backup_nginx.sh。
5. 无代理=只需 SSH;声明式=写目标状态;幂等=重复执行结果一致。
6. -m shell / -m command / -m ping;apt 模块 + systemd 模块最小 playbook。
7. 密码会随脚本分发/进 Git/进备份泄露;用环境变量、密钥、Vault。