Bash脚本 - Nginx 日志分析工具:统计网站的总数据流量、请求数、和各个IP的具体数据
https://www.nodeseek.com/post-291808-1
#Script #Shell #Tool
https://www.nodeseek.com/post-291808-1
#!/bin/bash
LOG_DIR="/opt/1panel/apps/openresty/openresty/www/sites"
# 人类可读的流量格式化函数
format_size() {
local size=$(printf "%.0f" "$1")
if (( size < 1024 )); then
echo "${size} B"
elif (( size < 1048576 )); then
echo "$(( size / 1024 )) KB"
elif (( size < 1073741824 )); then
echo "$(( size / 1048576 )) MB"
else
echo "$(( size / 1073741824 )) GB"
fi
}
# 列出所有网站并统计汇总数据
list_sites() {
local total_requests=0
local total_traffic=0
declare -A site_requests
declare -A site_traffic
echo "📌 站点列表:"
for site in "$LOG_DIR"/*; do
[[ -d "$site" ]] || continue
site_name=$(basename "$site")
log_path="$site/log/access.log"
if [[ ! -f "$log_path" ]]; then
echo " ❌ $site_name (无日志)"
continue
fi
# 统计该站点请求数 & 总流量
requests=$(wc -l < "$log_path")
traffic=$(awk '{size=$10} size ~ /^[0-9]+$/ {sum += size} END {printf "%.0f", sum}' "$log_path")
traffic=${traffic:-0}
site_requests["$site_name"]=$requests
site_traffic["$site_name"]=$traffic
total_requests=$((total_requests + requests))
total_traffic=$((total_traffic + traffic))
echo " ✅ $site_name - 请求数: $requests, 流量: $(format_size "$traffic")"
done
# 汇总数据
echo -e "\n📊 **站点总览**"
echo " 🌐 站点总数: ${#site_requests[@]}"
echo " 📥 总请求数: $total_requests"
echo " 📊 总流量: $(format_size "$total_traffic")"
# 按请求数 & 流量 排序站点
echo -e "\n📈 **Top 5 站点 (按请求数)**"
for site in "${!site_requests[@]}"; do
echo "${site_requests[$site]} $site"
done | sort -nr | head -n 5 | awk '{printf " %-15s 请求数: %s\n", $2, $1}'
echo -e "\n💾 **Top 5 站点 (按流量)**"
for site in "${!site_traffic[@]}"; do
echo "${site_traffic[$site]} $site"
done | sort -nr | head -n 5 | while read -r size site; do
echo " $site 流量: $(format_size "$size")"
done
}
# 筛选 IP 日志
extract_ip_logs() {
local ip="$1"
local output_file="$2"
local found=0
echo "📂 正在搜索与 IP $ip 相关的日志..."
> "$output_file" # 清空输出文件
for site in "$LOG_DIR"/*; do
[[ -d "$site" ]] || continue
log_path="$site/log/access.log"
if [[ -f "$log_path" ]]; then
# 检测日志文件类型
if file "$log_path" | grep -q "gzip compressed data"; then
zgrep -a -F "$ip" "$log_path" >> "$output_file"
else
grep -a -F "$ip" "$log_path" >> "$output_file"
fi
found=1
fi
done
if [[ $found -eq 1 ]]; then
echo "✅ 日志已保存到: $output_file"
else
echo "❌ 没有找到与 $ip 相关的日志!"
fi
}
# 解析命令行参数
if [[ $# -eq 2 && "$1" == "-n" ]]; then
SITE="$2"
LOG_PATH="$LOG_DIR/$SITE/log/access.log"
if [[ ! -f "$LOG_PATH" ]]; then
echo "错误: 访问日志 $LOG_PATH 不存在!"
exit 1
fi
echo "日志文件: $LOG_PATH"
# 统计请求最多的 10 个 IP
echo -e "\n📊 请求数最多的 IP:"
awk '{print $1}' "$LOG_PATH" | sort | uniq -c | sort -nr | head -n 10 | awk '{printf " %-15s 请求数: %s\n", $2, $1}'
# 统计流量最多的 10 个 IP
echo -e "\n📊 消耗带宽最多的 IP:"
awk '{ip=$1; size=$10} size ~ /^[0-9]+$/ {traffic[ip] += size} END {for (ip in traffic) printf "%.0f %s\n", traffic[ip], ip}' "$LOG_PATH" \
| sort -nr | head -n 10 | while read -r size ip; do
echo " $ip 流量: $(format_size "$size")"
done
elif [[ $# -eq 1 && "$1" == "-v" ]]; then
list_sites
elif [[ $# -eq 3 && "$1" == "-i" ]]; then
extract_ip_logs "$2" "$3"
else
echo "用法:"
echo " $0 -n # 查看指定站点的流量信息"
echo " $0 -v # 列出所有站点并显示汇总数据"
echo " $0 -i <文件> # 筛选出指定 IP 的日志并保存"
exit 1
fi参数 说明 示例
-n 查看指定站点的流量 & 请求统计 ./statics.bash -n example.com
-v 列出所有站点的流量 & 请求数汇总 ./statics.bash -v
-i <文件> 筛选指定 IP 访问日志并输出到文件 ./statics.bash -i 1.1.1.1 ./sus.log#Script #Shell #Tool