Shell脚本高手速成:5个头条运维工程师都在用的实战秘籍
《Shell脚本高手速成:5个头条运维工程师都在用的实战秘籍》
深知读者需要的是立即能用的干货。今天分享的这5个Shell脚本案例,都是从生产环境中总结的真实解决方案,包含了很多网上找不到的实用技巧。
一、日志分析神器:实时监控Nginx异常请求
痛点:传统的日志分析工具太重,小团队需要轻量级方案
bash
#!/bin/bash
# 文件名:nginx_alert.sh
# 功能:实时监控Nginx 5xx错误和慢请求
LOG_PATH="/var/log/nginx/access.log"
ALERT_EMAIL="team@example.com"
ERROR_THRESHOLD=10 # 每分钟错误数阈值
SLOW_TIME=3 # 慢请求阈值(秒)
tail -F $LOG_PATH | while read line; do
# 提取关键字段
status=$(echo $line | awk '{print $9}')
request_time=$(echo $line | awk '{print $10}')
url=$(echo $line | awk '{print $7}')
# 错误请求监控
if [[ "$status" =~ ^5[0-9]{2}$ ]]; then
echo "$(date) [ERROR] $status $url" >> /var/log/nginx_error.log
error_count=$((error_count + 1))
fi
# 慢请求监控
if (( $(echo "$request_time > $SLOW_TIME" | bc -l) )); then
echo "$(date) [SLOW] ${request_time}s $url" >> /var/log/nginx_slow.log
fi
# 每分钟错误数检查
current_minute=$(date +%M)
if [[ "$current_minute" != "$last_minute" ]]; then
if (( error_count > ERROR_THRESHOLD )); then
echo "紧急:检测到${error_count}次5xx错误" | mail -s "Nginx错误激增" $ALERT_EMAIL
fi
error_count=0
last_minute=$current_minute
fi
done
使用技巧:
1.用tail -F替代-f,防止日志轮转时丢失数据
2.bc -l处理浮点数比较
3.每分钟重置计数器避免误报
二、服务器健康报告:比Zabbix更轻量的选择
创新点:将多台服务器的状态汇总成一份精美的HTML报告
bash
#!/bin/bash
# 文件名:server_report.sh
# 功能:生成可视化服务器健康报告
OUTPUT_FILE="/var/www/html/server_report.html"
SERVERS=("web1" "web2" "db1")
# HTML头部
cat > $OUTPUT_FILE <<EOF
<html>
<head>
<style>
.critical { background-color: #ffcccc; }
.warning { background-color: #ffffcc; }
</style>
</head>
<body>
<h1>服务器健康报告 $(date)</h1>
<table border="1">
<tr>
<th>主机名</th>
<th>CPU负载</th>
<th>内存使用</th>
<th>磁盘空间</th>
<th>服务状态</th>
</tr>
EOF
# 收集每台服务器数据
for server in ${SERVERS[@]}; do
ssh $server "
# 获取CPU负载(1分钟)
cpu_load=\$(awk '{print \$1}' /proc/loadavg)
# 获取内存使用率
mem_usage=\$(free -m | awk '/Mem/{printf \"%.1f%%\", \$3/\$2*100}')
# 获取根分区使用率
disk_usage=\$(df -h / | awk 'NR==2{print \$5}')
# 检查Nginx服务状态
if systemctl is-active nginx &>/dev/null; then
nginx_status=\"<span style='color:green'>运行中</span>\"
else
nginx_status=\"<span style='color:red'>已停止</span>\"
fi
# 输出表格行
echo \"<tr>
<td>$server</td>
<td>\$cpu_load</td>
<td>\$mem_usage</td>
<td>\$disk_usage</td>
<td>\$nginx_status</td>
</tr>\"
" >> $OUTPUT_FILE
done
# HTML尾部
cat >> $OUTPUT_FILE <<EOF
</table>
<p>生成时间:$(date "+%Y-%m-%d %H:%M:%S")</p>
</body>
</html>
EOF
# 发送通知
echo "健康报告已生成:http://your-server/server_report.html" | mail -s "每日服务器报告" $ALERT_EMAIL
亮点功能:
1.通过SSH远程收集数据
2.自动生成带样式的HTML表格
3.关键指标高亮显示
三、智能备份方案:MySQL数据库的自动化备份
行业痛点:传统备份方案要么太简单(只有全量),要么太复杂(需要专业软件)
bash
#!/bin/bash
# 文件名:mysql_backup.sh
# 功能:智能MySQL备份(全量+增量)
DB_USER="backup_user"
DB_PASS="secure_password"
BACKUP_DIR="/backup/mysql"
DATE=$(date +%Y%m%d)
FULL_BACKUP_DAY="Sun" # 每周日全量备份
# 创建备份目录
[ -d "$BACKUP_DIR" ] || mkdir -p "$BACKUP_DIR"
# 判断是否全量备份日
if [ "$(date +%a)" = "$FULL_BACKUP_DAY" ]; then
BACKUP_TYPE="full"
BACKUP_FILE="$BACKUP_DIR/full_$DATE.sql.gz"
# 全量备份
mysqldump -u$DB_USER -p$DB_PASS --all-databases \
--single-transaction \
--flush-logs \
--master-data=2 \
--routines \
--events | gzip > $BACKUP_FILE
# 记录binlog位置
mysql -u$DB_USER -p$DB_PASS -e "SHOW MASTER STATUS" > $BACKUP_DIR/binlog_pos.txt
else
BACKUP_TYPE="incremental"
LAST_BINLOG=$(cat $BACKUP_DIR/binlog_pos.txt | awk 'NR==2{print $1}')
LAST_POS=$(cat $BACKUP_DIR/binlog_pos.txt | awk 'NR==2{print $2}')
BACKUP_FILE="$BACKUP_DIR/incr_$DATE.sql.gz"
# 增量备份
mysqlbinlog --start-position=$LAST_POS \
/var/lib/mysql/$LAST_BINLOG | gzip > $BACKUP_FILE
# 更新binlog位置
mysql -u$DB_USER -p$DB_PASS -e "SHOW MASTER STATUS" > $BACKUP_DIR/binlog_pos.txt
fi
# 保留30天备份
find $BACKUP_DIR -name "*.sql.gz" -mtime +30 -delete
# 上传到云存储(阿里云OSS示例)
ossutil cp $BACKUP_FILE oss://your-bucket/mysql_backup/ --config-file /etc/ossutil.conf
专业特性:
1.每周全量+每日增量备份策略
2.使用--single-transaction确保数据一致性
3.自动清理旧备份
4.支持上传到云存储
四、端口安全检测:快速发现异常开放端口
实用场景:服务器安全检查时快速发现风险点
bash
#!/bin/bash
# 文件名:port_check.sh
# 功能:快速检测异常开放端口
KNOWN_PORTS="22,80,443,3306" # 已知安全端口
ALERT_FILE="/var/log/port_alert.log"
# 获取本机所有监听端口
OPEN_PORTS=$(ss -tuln | awk '/LISTEN/{print $5}' | awk -F: '{print $NF}' | sort -nu)
# 检查未知端口
for port in $OPEN_PORTS; do
if ! grep -q "\<$port\>" <<< "$KNOWN_PORTS"; then
PROCESS=$(lsof -i :$port | awk 'NR==2{print $1}')
echo "$(date) [警告] 发现未知端口 $port, 进程: $PROCESS" >> $ALERT_FILE
# 获取连接详情(前5条)
CONN_INFO=$(ss -tup state established "sport = :$port" | head -5)
echo "连接详情:" >> $ALERT_FILE
echo "$CONN_INFO" >> $ALERT_FILE
echo "------------------------" >> $ALERT_FILE
fi
done
# 如果有异常则发送警报
if [ -s $ALERT_FILE ]; then
mail -s "服务器端口安全警报" security@example.com < $ALERT_FILE
> $ALERT_FILE # 清空日志文件
fi
技术亮点:
1.使用ss替代过时的netstat
2.自动关联端口和进程
3.记录连接详情便于分析
4.只关注非标准端口
五、自动化证书管理:SSL证书过期监控与续期
行业痛点:证书过期导致网站不可用的事故频发
bash
#!/bin/bash
# 文件名:ssl_check.sh
# 功能:自动检查证书过期时间并续期
DOMAINS=("example.com" "api.example.com" "blog.example.com")
WARNING_DAYS=30 # 提前30天提醒
CERT_DIR="/etc/nginx/ssl"
for domain in ${DOMAINS[@]}; do
cert_file="$CERT_DIR/$domain.crt"
# 获取过期时间
expire_date=$(openssl x509 -in $cert_file -enddate -noout | cut -d= -f2)
expire_ts=$(date -d "$expire_date" +%s)
current_ts=$(date +%s)
remaining_days=$(( (expire_ts - current_ts) / 86400 ))
# 检查是否需要续期
if [ $remaining_days -lt $WARNING_DAYS ]; then
echo "$(date) 域名 $domain 证书将在 $remaining_days 天后过期" >> /var/log/ssl_check.log
# 自动续期(Certbot示例)
if certbot renew --cert-name $domain --nginx --quiet; then
echo "$(date) 成功续期 $domain" >> /var/log/ssl_check.log
systemctl reload nginx
else
echo "$(date) [错误] $domain 续期失败" | mail -s "证书续期警报" admin@example.com
fi
fi
done
# 每周清理旧日志
find /var/log/ssl_check.log -mtime +30 -exec rm {} \;
最佳实践:
1.支持多域名检查
2.自动续期+通知双保险
3.与Nginx无缝集成
4.完善的日志管理
技术总结:Shell脚本的现代应用法则
1.错误处理:所有关键操作都应检查返回值
bash
if ! openssl x509 -in cert.crt -noout &>/dev/null; then echo "证书文件无效" >&2 exit 1 fi
2.性能优化:避免不必要的子shell
# 不好 free_mem=$(free -m | awk '/Mem/{print $4}') # 更好 read _ total used _ <<< "$(free -m | grep Mem)" free_mem=$((total - used))
3.安全规范:
# 密码处理 read -s -p "输入密码: " password echo # 敏感信息不记录日志 command >/dev/null 2>&1
如果你有特别想了解的Shell场景,欢迎在评论区留言交流!