前几课,你学了一整套 shell 武器:变量、判断、循环、函数、管道、三剑客。但光会写还不够——一个能上生产的脚本,还得健壮(出错能处理)、能定时自动跑(cron)、好排错。这一课,我们把知识合起来,写一个真正能用的自动化运维脚本,并让它按时自动执行。这是第七阶段(Shell 与脚本编程)的收官课。

从"人工运维"到"自动运维"

想象你每天要做这些事:备份文件、检查磁盘和内存、清理旧备份、记日志。天天手动敲一遍,又累又容易忘。

自动化运维脚本就是解法:把这些事写成一个脚本,再用 cron 定时执行——到点它自己跑,你睡大觉。这一课,我们把这个流程完整走一遍。


28.1 综合脚本的结构

一句话理解:一个合格的运维脚本 = 头部(#!/bin/bash + set -euo pipefail)+ 配置区(路径/阈值)+ 核心逻辑 + 日志输出 + 退出码。

一个合格脚本,结构清晰、分块:

#!/bin/bash               # 1. 头部:指定解释器
set -euo pipefail         #    健壮开头

# ---- 配置区 ----
SRC="$HOME/Documents"     # 2. 配置:路径、阈值等,集中放前面,好改
BACKUP_DIR="$HOME/backups"

# ---- 核心逻辑 ----        # 3. 真正干活的地方
...

# ---- 日志输出 ----        # 4. 记录做了什么
...

exit 0                     # 5. 退出码
为什么配置要集中放前面?因为路径、阈值这些"以后会改"的东西,集中起来一眼就能改,不用满脚本找。

28.2 cron 定时任务

一句话理解:cron 是"定时器",crontab -e 编辑,格式是 分 时 日 月 周 命令,到点自动跑。

写好了脚本,怎么让它"每天自动跑"?靠 cron

编辑定时任务:crontab -e,加一行:

分 时 日 月 周 命令

五个时间字段,从"分"到"周":

字段范围含义
0-59第几分钟
0-23第几小时
1-31几号
1-12几月
0-7(0 和 7 都是周日)星期几

例子:

  • 0 2 * * * /home/user/backup.sh每天凌晨 2 点跑备份(* 表示"任意");
  • */5 * * * * /path/check.sh每 5 分钟一次(*/5 表示"每隔 5");
  • 0 3 * * 1 /path/weekly.sh每周一凌晨 3 点

28.3 健壮性技巧

一句话理解trap '清理动作' EXIT 让脚本退出前必做清理;set -u 防未定义变量;logger 把日志写进系统日志。

三个让脚本更皮实的技巧:

trap——退出前必做清理

trap 'echo "备份中断" >> "$LOG"' ERR   # 出错时记录
trap 'rm -f /tmp/tmpfile' EXIT         # 无论成功失败,退出前删临时文件
trap 监听某个"信号"或"退出"事件,触发时执行指定动作。这样脚本中途出错,也能清理临时文件、不留垃圾

set -u:上一课讲过,用未定义变量就报错,防拼写错误。

logger:把日志写进系统日志(而不是只写自己的文件):

echo "⚠️ 磁盘使用 95%" | logger -t monitor
logger -t monitor 给这条日志打上 monitor 标签,写进系统日志,方便集中监控。

28.4 排错思路

脚本出问题了,按这个顺序排查:

一句话理解:先 bash -x script.sh 逐条看执行到哪出错,再看退出码和 stderr,最后检查权限、路径、环境变量。
  1. bash -x script.sh:逐条打印每条命令(前面带 +),看执行到哪一步出错
  2. 看退出码和 stderrecho $? 看退出码,stderr 的错误信息往往直接指出原因;
  3. 检查权限、路径、环境变量:文件有可执行权限吗?路径对了吗?
cron 报错的经典坑:cron 运行环境不读 ~/.bashrcPATH 极简。你在终端能跑的脚本,cron 里可能找不到命令。所以 cron 里的脚本要用绝对路径,或显式设置 PATH

动手实验:备份 + 监控脚本

备份脚本

#!/bin/bash
set -euo pipefail

# ---- 配置区 ----
SRC="$HOME/Documents"
BACKUP_DIR="$HOME/backups"
KEEP=7
LOG="$BACKUP_DIR/backup.log"

mkdir -p "$BACKUP_DIR"
trap 'echo "备份中断" >> "$LOG"' ERR

# ---- 备份 ----
stamp=$(date +%Y%m%d_%H%M%S)
tar -czf "$BACKUP_DIR/doc_$stamp.tar.gz" -C "$SRC" . >> "$LOG" 2>&1
echo "[$stamp] 备份完成" >> "$LOG"

# ---- 清理旧备份,只保留最近 KEEP 份 ----
ls -1t "$BACKUP_DIR"/doc_*.tar.gz | tail -n +$((KEEP+1)) | xargs -r rm -f

监控脚本(磁盘 + 内存水位):

#!/bin/bash
set -uo pipefail
DISK_TH=90
MEM_TH=90

disk=$(df / | awk 'NR==2 {gsub("%","",$5); print $5}')
mem=$(free | awk 'NR==2 {printf "%.0f", $3/$2*100}')

[ "$disk" -gt "$DISK_TH" ] && echo "⚠️ 磁盘使用 ${disk}%" | logger -t monitor
[ "$mem" -gt "$MEM_TH" ] && echo "⚠️ 内存使用 ${mem}%" | logger -t monitor

配 cron:

crontab -e
# 加一行:
0 3 * * * /home/user/backup.sh

明天凌晨 3 点自动备份。观察 $LOGlogger 写入的系统日志。

读一遍监控脚本:df / 取磁盘,awk 'NR==2' 取第 2 行、gsub("%","",$5) 去掉第 5 列的百分号——得到磁盘使用率数字;free 同理算出内存使用率;超过阈值就 logger 告警。每一行都是前几课的知识拼起来的。

深入点:两个进阶话题

① cron 的环境陷阱

cron 不读 ~/.bashrcPATH 极简。所以脚本里最好写绝对路径(如 /usr/bin/tar 而不是 tar),或显式 export PATH=...

② 锁文件防重入

定时任务可能还没跑完又被触发(比如每 5 分钟一次,但某次跑了 10 分钟)。防止并发执行:

flock -n /tmp/backup.lock ./backup.sh
flock -n:拿到锁才执行,拿不到(说明上次还没跑完)就直接退出,避免两个实例同时跑、互相打架。

小结与思考题

这一课,我们把知识合成了一个真正的运维脚本:

  • 脚本结构:头部 + 配置区 + 核心逻辑 + 日志 + 退出码;
  • cron分 时 日 月 周 命令,定时自动跑;
  • 健壮性trap 清理、set -ulogger 写系统日志;
  • 排错bash -x 逐条看 → 退出码/stderr → 权限/路径/环境。

留三个问题:

  1. 一个健壮脚本的标准开头是什么?
  2. cron 的时间格式怎么读?
  3. 为什么 cron 里的脚本常要用绝对路径?
到这里,第七阶段(Shell 与脚本编程,25~28 课)收官。前面我们一直在"一台机器"里打转。但现代系统,几乎都是跑在云上、容器里的。你可能天天用 Docker,却未必想过:Docker 到底借用了 Linux 内核的哪些能力,才做到"秒级启动、互相隔离"? 它和虚拟机有什么本质区别?下一课,我们进入第八阶段:虚拟化与容器,把 Docker 的"黑魔法"拆开看。

标签: 计算机基础, 操作系统, Linux

添加新评论