第 11 章 · 脚本自动化与批量运维
「每次都是搜索或问 AI」的根源是没把重复操作固化成自己的工具。本章让你学会用 Bash 脚本把日常操作自动化,再用 Ansible 把「一台服务器」的管理复制到「一百台」—— 这正是运维从入门到专业的分水岭。
11.1脚本思维:把「你会手动做的事」写下来
一个实用的进阶路径:先手动做一遍成功 → 把命令按顺序写成脚本 → 加判断与日志 → 挂 cron → 多台机器用 Ansible 铺开。你不是在学编程语言,是在「把操作记录成可复用的流程」。
11.2Bash 脚本语法速成(30 分钟够用)
#!/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:数据库每日备份
#!/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 章加固写进去)
#!/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:服务健康检查 + 自愈
#!/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定时与触发:让脚本自己跑
- cron(第 7 章):日常周期任务首选。
crontab -e编辑,注意绝对路径与环境变量。 - systemd timer:需要错过补跑/精确控制时用(进阶)。
- 触发式:rsync 同步后执行、文件变化触发(inotifywait)等。
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脚本安全习惯(写脚本的三条红线)
- 不把密码写死在脚本:用环境变量、密钥文件、
pass/Vault 等;脚本里的密码会随着备份/分享泄露。 - set -euo pipefail 开头:失败即停,避免「脚本报错还继续往下跑造成更大破坏」。
- rm 前的防护:删除类操作加路径校验(
[[ $DIR == /data/* ]]才允许删),防止变量为空变成rm -rf /。 - 上传到 Git 前检查:
grep -iE "password|secret|token" 脚本。
本章自测题
- Bash 脚本第一行必须写什么?set -euo pipefail 三个各防什么?
- if 判断文件存在、for 循环遍历 IP 的语法各写一遍。
- 如何调试脚本(逐行打印)?如何只看语法?
- 写一个「每天备份 nginx 配置目录,保留 7 份,删除更旧的」脚本并挂 cron。
- Ansible 的三种特点(无代理/声明式/幂等)各是什么意思?
- Ansible 批量执行命令用什么模块?批量安装软件写 playbook 的最小例子?
- 脚本里为什么不能写死密码?替代方案?
参考答案
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。