文章目录
一、为什么说Shell是程序员的瑞士军刀?(必看)
最近帮学弟排查服务器故障时(CPU莫名飙高的情况),发现他连最基础的进程监控脚本都不会写(震惊.jpg)。这让我意识到,虽然现在Python大行其道,但真正玩转Linux的老司机都知道——Shell脚本才是系统管理的神器!!!
举个真实案例:上个月我们线上服务器遭遇恶意扫描,通过编写20行的Shell脚本(包含netstat+awk+grep组合技),5分钟就锁定了异常IP。这种即时响应能力是其他语言难以比拟的(Python此时还在import各种库呢~)
二、新手避坑指南:这些错误90%的人都犯过
1. 文件路径的隐藏陷阱
# 错误示范 ❌
cd /var/log
grep "error" app.log
# 正确姿势 ✔️
cd /var/log || exit 1
grep -i "error" app.log > /tmp/error.log 2>&1
重点解析:
|| exit 1
防止目录切换失败后继续执行危险操作- 重定向标准错误输出(2>&1)避免漏掉关键信息
- 使用绝对路径更安全(特别是crontab场景)
2. 变量使用的三大天坑
# 典型错误集锦
name = "张三" # 等号两边不能有空格
echo $name$age # 未定义变量导致命令拼接异常
rm -rf $dir/* # 变量未检查直接使用(危险!)
避坑口诀:
- 等号紧贴两边(name=“value”)
- 双引号包裹变量(echo “${name}”)
- 变量检查三步走:
[[ -d "$dir" ]] || { echo "目录不存在"; exit 1; }
[[ -n "$user" ]] || user="default"
readonly config_file="/etc/app.conf"
三、实战案例库(精选TOP10)
案例3:自动封禁暴力破解IP(安全运维必备)
#!/bin/bash
# 自动封禁SSH暴力破解IP
FAILED_LOG="/var/log/auth.log"
ATTEMPTS=5
# 获取可疑IP
grep "Failed password" $FAILED_LOG | awk '{print $(NF-3)}' | sort | uniq -c | while read count ip
do
if [[ $count -gt $ATTEMPTS ]]; then
# 检查是否已封禁
if ! iptables -L INPUT -n | grep -q "$ip"; then
iptables -A INPUT -s $ip -j DROP
echo "$(date) 封禁IP:$ip 尝试次数:$count" >> /var/log/iptables_ban.log
fi
fi
done
技术要点:
- awk提取特定字段(NF表示最后一个字段)
- while循环处理每一行结果
- iptables规则查重机制
- 日志记录规范
案例7:智能备份脚本(带过期清理)
#!/bin/bash
BACKUP_DIR="/backups"
MAX_DAYS=30
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
# 创建当日备份
tar -czf $BACKUP_DIR/app_$TIMESTAMP.tar.gz /var/www/html 2>/dev/null
# 清理旧备份
find $BACKUP_DIR -name "*.tar.gz" -mtime +$MAX_DAYS -exec rm {} \;
# 空间不足预警
USAGE=$(df -h $BACKUP_DIR | awk 'NR==2 {print $5}' | tr -d '%')
[[ $USAGE -gt 90 ]] && echo "警告:备份目录使用率已达${USAGE}%" | mail -s "存储告警" admin@example.com
亮点解析:
- 时间戳命名避免覆盖
- find命令自动清理过期文件
- 存储空间智能监控
- 静默模式处理打包错误
(由于篇幅限制,更多案例已整理成速查表👇)
四、高级技巧:让你的脚本专业度提升200%
1. 信号捕获与优雅退出
trap cleanup SIGINT SIGTERM
cleanup() {
echo "正在清理临时文件..."
rm -rf /tmp/temp_*
exit 1
}
# 模拟长时间任务
sleep 300
应用场景:
- Ctrl+C终止时执行清理
- 防止脚本中断导致系统残留
- 关键操作回滚
2. 并发控制黑科技
# 使用命名管道实现并发控制
FIFO_FILE="/tmp/$$.fifo"
mkfifo $FIFO_FILE
exec 6<>$FIFO_FILE
rm -f $FIFO_FILE
# 设置最大并发数
THREAD_NUM=10
for ((i=0;i<$THREAD_NUM;i++))
do
echo
done >&6
# 任务示例
for ip in 192.168.1.{1..254}
do
read -u6
{
ping -c1 $ip &>/dev/null && echo "$ip is alive"
echo >&6
} &
done
wait
exec 6>&-
原理揭秘:
- 利用文件描述符实现进程池
- 命名管道控制并发数量
- 避免fork炸弹风险
五、调试技巧大全(附赠排错流程图)
调试三板斧:
- 语法检查:
bash -n script.sh
- 执行追踪:
bash -x script.sh
- 即时调试:
set -e # 出错立即退出
set -u # 使用未定义变量时报错
set -o pipefail # 管道命令失败时捕获错误
排错流程图:
脚本报错 → 查看错误行号 → 检查变量作用域 → 验证命令权限 → 测试边界条件 → 模拟特殊字符 → 检查环境变量 → 确认依赖版本
六、资源推荐(少走弯路必备)
1. 在线验证神器
- ShellCheck:实时语法检查工具
- ExplainShell:命令解析神器
2. 进阶书籍
- 《Linux命令行与Shell脚本编程大全》(第三版)
- 《Bash Cookbook》(O’Reilly出品)
3. 常用函数库
# 颜色输出函数
function color_echo() {
local color=$1
shift
case $color in
red) echo -e "\033[31m$*\033[0m";;
green) echo -e "\033[32m$*\033[0m";;
yellow) echo -e "\033[33m$*\033[0m";;
*) echo "$*";;
esac
}
# 使用示例
color_echo red "重要错误!"
color_echo green "操作成功!"
最后叮嘱:看完这篇教程后,强烈建议把/etc目录下的所有*.sh脚本都研究一遍(系统级的教学案例啊!)。坚持每天写1个实用脚本,三个月后你会回来感谢我的(认真脸)~