掌握了Bash的基础知识后,是时候将它们组合起来,创建能真正帮你解决问题的脚本了。无论是系统管理、日常维护还是监控告警,编写Bash脚本实现自动化都应该是你的最终目标。它能将你从枯燥、重复的体力劳动中解放出来,把精力留给更需要创造性的工作。
本文将展示几个自动化脚本的实战案例,你可以直接使用,也可以根据需求进行扩展,打造属于自己的自动化工具箱。
自动化用户管理
在多台服务器上批量创建或管理用户,是系统管理员常见的日常工作。这项任务既枯燥又重复,非常适合用脚本来自动完成。
首先,你需要创建一个文本文件(例如 servers.txt),列出所有目标服务器的主机名或IP地址。
假设我们有5台服务器,文件内容如下:
sean@debian-12:~$ cat servers.txt
server1
server2
server3
server4
server5
注:这里假设这些主机名已经配置在 /etc/hosts 文件中,并且 SSH 免密登录已经设置好。如果使用IP地址,直接替换为主机名即可。
接下来,我们来看 adduser.sh 脚本的代码:
#!/bin/bash
servers=$(cat servers.txt)
echo -n "Enter the username: "
read name
echo -n "Enter the user id: "
read uid
for i in $servers; do
echo $i
ssh $i "sudo useradd -m -u $uid $name"
if [ $? -eq 0 ]; then
echo "User $name added on $i"
else
echo "Error on $i"
fi
done
这个脚本的工作流程很清晰:
- 读取
servers.txt 文件,获取服务器列表。
- 提示用户输入要创建的用户名(
name)和用户ID(uid)。
- 通过
for 循环遍历每台服务器。
- 使用
ssh 远程连接到服务器,并执行 sudo useradd 命令创建用户(-m 选项会创建家目录)。
- 通过检查上一条命令的退出状态
$? 来判断是否执行成功,并给出相应提示。
现在运行这个脚本,看看效果:

脚本运行成功,用户 jerry 被添加到了所有目标服务器上。这里有几个关键点需要理解:
- SSH免密登录:为了让脚本完全自动化,建议提前配置好 SSH 密钥对,避免每次连接都输入密码。
- 权限要求:执行
useradd 命令需要 root 权限,因此脚本中使用了 sudo。确保执行脚本的用户在目标服务器上有相应的 sudo 权限。
想象一下,如果你需要在几十上百台服务器上执行相同的操作,这个简单的脚本将为你节省大量时间。
自动备份
备份数据是系统运维管理员的另一项核心工作。手动备份不仅容易出错,还难以坚持。下面这个 backup.sh 脚本可以帮你实现自动化备份。
#!/bin/bash
backup_dirs=("/etc" "/home" "/boot")
dest_dir="/backup"
dest_server="server1"
backup_date=$(date +%y-%m-%d)
echo "Starting backup of: ${backup_dirs[@]}"
for i in "${backup_dirs[@]}"; do
sudo tar -Pczf /tmp/$i-$backup_date.tar.gz $i
if [ $? -eq 0 ]; then
echo "$i backup succeeded."
else
echo "$i backup failed."
fi
scp /tmp/$i-$backup_date.tar.gz $dest_server:$dest_dir
if [ $? -eq 0 ]; then
echo "$i transfer succeeded."
else
echo "$i transfer failed."
fi
done
sudo rm /tmp/*.gz
echo "Backup is done."
脚本解析:
backup_dirs 数组:定义了需要备份的目录,这里包括 /etc(配置文件)、/home(用户数据)和 /boot(启动文件)。
- 关键变量:
dest_dir:远程备份服务器上的目标目录。
dest_server:备份服务器的地址。
backup_date:以 年-月-日 格式获取当前日期,用于给备份文件命名,避免覆盖。
- 核心循环:遍历每个需要备份的目录。
- 使用
tar 命令将该目录压缩打包到本地 /tmp 目录下。
- 使用
scp 命令将打包好的压缩文件传输到远程备份服务器。
- 每一步都检查命令执行状态并输出结果。
- 清理:删除本地
/tmp 目录下临时生成的压缩包。
这个脚本清晰地勾勒出了一个备份流程:本地打包 -> 远程传输 -> 清理临时文件。

运行脚本,你会看到类似下面的输出:
sean@debian-12:~$ ./backup.sh
Starting backup of: /etc /home /boot
/etc backup succeeded.
etc-Aug-30-20.tar.gz 100% 1288KB 460.1KB/s 00:02
/etc transfer succeeded.
/home backup succeeded.
home-Aug-30-20.tar.gz 100% 2543KB 547.0KB/s 00:04
/home transfer succeeded.
/boot backup succeeded.
boot-Aug-30-20.tar.gz 100% 105MB 520.2KB/s 03:26
/boot transfer succeeded.
Backup is done.

更进一步,如果我们希望这个备份任务每天凌晨自动执行,可以借助 cron 定时任务。只需一行配置:
sean@debian-12:~$ crontab -e
# 在打开的编辑器中添加下行,表示每天0点0分执行脚本
0 0 * * * /home/sean/scripts/backup.sh
监控磁盘可用空间
磁盘空间耗尽可能导致服务不可用甚至系统崩溃。主动监控比被动抢救要好得多。我们可以使用 df 命令查看磁盘使用情况。
sean@debian-12:~$ df -h / /apps /database
Filesystem Size Used Avail Use% Mounted on
/dev/sda5 20G 7.9G 11G 44% /
/dev/mapper/vg1-applv 4.9G 2.4G 2.3G 52% /apps
/dev/mapper/vg1-dblv 4.9G 4.5G 180M 97% /database
从输出看,/database 分区的使用率已经高达97%,情况危急。我们可以用 awk 等命令提取出使用率百分比。下面这个 disk_space.sh 脚本实现了自动监控和告警:
#!/bin/bash
filesystems=("/" "/apps" "/database")
for i in ${filesystems[@]}; do
usage=$(df -h $i | tail -n 1 | awk '{print $5}' | cut -d % -f1)
if [ $usage -ge 90 ]; then
alert="Running out of space on $i, Usage is: $usage%"
echo "Sending out a disk space alert email."
echo $alert | mail -s "$i is $usage% full" your_email@example.com
fi
done
脚本逻辑:
- 将需要监控的文件系统(挂载点)放入
filesystems 数组。
- 循环处理每个文件系统:
- 通过
df -h $i 获取该分区的信息。
- 用
tail -n 1 取最后一行(即目标分区的信息)。
- 用
awk ‘{print $5}’ 提取第五列(使用率,如 97%)。
- 用
cut -d % -f1 去掉百分号,得到纯数字 97。
- 判断:如果使用率
$usage 大于等于90,则准备告警信息,并通过 mail 命令发送邮件到指定邮箱。
请务必将脚本中的 your_email@example.com 替换为你自己的真实邮箱地址。
运行脚本:
sean@debian-12:~$ ./disk_space.sh
Sending out a disk space alert email.
随后,你就能在邮箱中收到告警邮件了。同样,我们可以用 cron 让监控定期进行,例如每6小时检查一次:
sean@debian-12:~$ crontab -e
# 添加以下行
0 */6 * * * /home/sean/scripts/disk_space.sh
练习题与参考答案
理论学习之后,动手实践是巩固知识的最佳方式。以下是基于本文内容的练习题,涵盖了从脚本编写到定时任务配置的全流程。
练习 1:在服务器上自动化用户管理
目标:编写一个Bash脚本,自动在 servers.txt 文件列出的多台服务器上创建指定用户。
难度:困难
提示:参照文中 adduser.sh 脚本,核心是循环读取服务器列表,并通过SSH远程执行 useradd 命令。
练习 2:自动备份到一个单独的服务器
目标:编写脚本,将本地多个指定目录备份到另一台远程服务器。
难度:困难
提示:使用数组定义备份目录,使用 tar 打包,使用 scp 传输,并包含成功/失败的状态反馈。
练习 3:定期自动备份
目标:配置 cron,让练习2中的备份脚本每天午夜自动执行。
难度:中等
练习 4:自动监控可用磁盘空间
目标:编写脚本,监控指定分区的磁盘使用率,当超过阈值(如90%)时发送邮件告警。
难度:困难
提示:结合 df、tail、awk、cut 命令提取使用率百分比,并使用 mail 命令发信。
练习 5:定期自动监控磁盘空间
目标:配置 cron,让练习4中的监控脚本每6小时运行一次。
难度:中等
练习 6:自动执行磁盘空间监控和定时备份
目标:在 cron 中同时配置备份任务(每天午夜)和磁盘监控任务(每6小时)。
难度:中等
参考答案
练习1 答案脚本 adduser.sh:
#!/bin/bash
servers=$(cat servers.txt)
echo -n "Enter the username: "
read name
echo -n "Enter the user id: "
read uid
for i in $servers; do
echo $i
ssh $i "sudo useradd -m -u $uid $name"
if [ $? -eq 0 ]; then
echo "User $name added on $i"
else
echo "Error on $i"
fi
done
练习2 答案脚本 backup.sh:
#!/bin/bash
backup_dirs=("/etc" "/home" "/boot")
dest_dir="/backup"
dest_server="server1"
backup_date=$(date +%b-%d-%y)
echo "Starting backup of: ${backup_dirs[@]}"
for i in "${backup_dirs[@]}"; do
sudo tar -Pczf /tmp/$i-$backup_date.tar.gz $i
if [ $? -eq 0 ]; then
echo "$i backup succeeded."
else
echo "$i backup failed."
fi
scp /tmp/$i-$backup_date.tar.gz $dest_server:$dest_dir
if [ $? -eq 0 ]; then
echo "$i transfer succeeded."
else
echo "$i transfer failed."
fi
done
sudo rm /tmp/*.gz
echo "Backup is done."
练习3 答案 cron 配置:
0 0 * * * /home/sean/scripts/backup.sh
练习4 答案脚本 disk_space.sh:
#!/bin/bash
filesystems=("/" "/apps" "/database")
for i in ${filesystems[@]}; do
usage=$(df -h $i | tail -n 1 | awk '{print $5}' | cut -d % -f1)
if [ $usage -ge 90 ]; then
alert="Running out of space on $i, Usage is: $usage%"
echo "Sending out a disk space alert email."
echo $alert | mail -s "$i is $usage% full" your_email@example.com
fi
done
练习5 答案 cron 配置:
0 */6 * * * /home/sean/scripts/disk_space.sh
练习6 答案 cron 配置:
# 每天午夜备份
0 0 * * * /home/sean/scripts/backup.sh
# 每6小时检查磁盘空间
0 */6 * * * /home/sean/scripts/disk_space.sh
通过以上实例和练习,相信你对如何使用 Bash 脚本解决实际的运维自动化问题有了更深的体会。记住,最好的学习方式就是模仿、修改并应用到自己的环境中。如果你有更多关于脚本编写的想法或问题,欢迎在云栈社区与我们交流。