查看Xray中各用户流量使用情况的脚本
来自md5.pw
更多语言
更多操作
预览
要求
Xray中需要配置, 分别开启 统计 / API / 本地策略, 且用户设置了email与level
配置参考:
{
"stats": {},
"api": {
"tag": "API",
"listen": "127.0.0.1:8080",
"services": [
"LoggerService",
"StatsService"
]
},
"policy": {
"levels": {
"0": {
"handshake": 5,
"connIdle": 600,
"statsUserUplink": true,
"statsUserDownlink": true,
"statsUserOnline": true
}
},
"system": {
"statsInboundUplink": true,
"statsInboundDownlink": true
}
}
}
用户配置参考:
{
"id": "UserId123456",
"email": "易于标识的名称",
"level": 0
}
内容
#!/usr/bin/env bash
set -euo pipefail
XRAY_BIN="${XRAY_BIN:-xray}"
# 自行修改 Xray API 地址
SERVER="${1:-127.0.0.1:8080}"
declare -A IN_UP IN_DOWN IN_TOTAL
declare -A U_UP U_DOWN U_TOTAL
declare -A USERSET
bytes_to_gb() {
local b="${1-}"
if [[ -z "${b}" ]]; then
echo "null"
return 0
fi
awk -v b="${b}" 'BEGIN{printf "%.3f", b/1024/1024/1024}'
}
normalize_stats_objects() {
tr -d '\n\r\t ' \
| grep -oE '\{"name":"[^"]+","value":[0-9]+\}'
}
extract_field() {
local obj="$1"
local key="$2"
echo "$obj" | sed -nE "s/.*\"${key}\":\"?([^\",}]*)\"?.*/\1/p"
}
accumulate_stats() {
local stats_json="$1"
local line name value kind tag dir email
while IFS= read -r line; do
[[ -z "$line" ]] && continue
name="$(extract_field "$line" "name")"
[[ -z "$name" ]] && continue
value="$(echo "$line" | sed -nE 's/.*"value":([0-9]+).*/\1/p')"
value="${value:-0}"
kind="$(awk -F'>>>' '{print $1}' <<<"$name")"
if [[ "$kind" == "inbound" ]]; then
tag="$(awk -F'>>>' '{print $2}' <<<"$name")"
dir="$(awk -F'>>>' '{print $4}' <<<"$name")"
if [[ "$dir" == "uplink" ]]; then
IN_UP["$tag"]=$(( ${IN_UP["$tag"]:-0} + value ))
elif [[ "$dir" == "downlink" ]]; then
IN_DOWN["$tag"]=$(( ${IN_DOWN["$tag"]:-0} + value ))
fi
IN_TOTAL["$tag"]=$(( ${IN_TOTAL["$tag"]:-0} + value ))
elif [[ "$kind" == "user" ]]; then
email="$(awk -F'>>>' '{print $2}' <<<"$name")"
dir="$(awk -F'>>>' '{print $4}' <<<"$name")"
USERSET["$email"]=1
if [[ "$dir" == "uplink" ]]; then
U_UP["$email"]=$(( ${U_UP["$email"]:-0} + value ))
elif [[ "$dir" == "downlink" ]]; then
U_DOWN["$email"]=$(( ${U_DOWN["$email"]:-0} + value ))
fi
U_TOTAL["$email"]=$(( ${U_TOTAL["$email"]:-0} + value ))
fi
done < <(echo "$stats_json" | normalize_stats_objects)
}
query_online_ips() {
local email="$1"
local out pairs status
out="$("$XRAY_BIN" api statsonlineiplist -s="$SERVER" -email "$email" 2>/dev/null || true)"
pairs="$(echo "$out" | tr -d '\n\r\t ' \
| grep -oE '"([0-9]{1,3}\.){3}[0-9]{1,3}":[0-9]+' \
| sed -E 's/"//g' \
| awk -F: '{
ip=$1
ts=$2
cmd="TZ=Asia/Shanghai date -d @"ts" \"+%Y-%m-%d %H:%M:%S\""
cmd | getline t
close(cmd)
printf "%s(%s) ", ip, t
}' \
| sed -E 's/[[:space:]]+$//')"
if [[ -n "$pairs" ]]; then
status="ONLINE"
echo "$status"
echo "$pairs"
else
echo "OFFLINE"
echo "-"
fi
}
main() {
local stats_json
stats_json="$("$XRAY_BIN" api statsquery --server="$SERVER" 2>/dev/null || true)"
#echo "$stats_json"
if [[ -z "$stats_json" ]]; then
echo "Server: $SERVER"
echo "Unit: GB, bytes divided by 1024^3"
echo
echo "Inbound traffic"
printf "%-22s %14s %14s %14s\n" "tag" "uplink_GB" "downlink_GB" "total_GB"
echo
echo "User traffic and online status"
printf "%-24s %14s %14s %14s %8s %s\n" "email" "uplink_GB" "downlink_GB" "total_GB" "status" "ips"
exit 0
fi
accumulate_stats "$stats_json"
echo "Server: $SERVER"
echo "Unit: GB, bytes divided by 1024^3"
echo
echo "Inbound traffic"
printf "%-22s %14s %14s %14s\n" "tag" "uplink_GB" "downlink_GB" "total_GB"
{
for tag in "${!IN_TOTAL[@]}"; do
echo "$tag"
done
} | sort | while IFS= read -r tag; do
local up down total up_s down_s total_s
if [[ -v IN_UP["$tag"] ]]; then up="${IN_UP["$tag"]}"; else up=""; fi
if [[ -v IN_DOWN["$tag"] ]]; then down="${IN_DOWN["$tag"]}"; else down=""; fi
if [[ -v IN_TOTAL["$tag"] ]]; then total="${IN_TOTAL["$tag"]}"; else total=""; fi
up_s="$(bytes_to_gb "$up")"
down_s="$(bytes_to_gb "$down")"
total_s="$(bytes_to_gb "$total")"
printf "%-22s %14s %14s %14s\n" "$tag" "$up_s" "$down_s" "$total_s"
done
echo
echo "User traffic and online status"
printf "%-24s %14s %14s %14s %8s %s\n" "email" "uplink_GB" "downlink_GB" "total_GB" "status" "ips"
{
for email in "${!USERSET[@]}"; do
echo "$email"
done
} | sort | while IFS= read -r email; do
local up down total up_s down_s total_s status ips
local qout
if [[ -v U_UP["$email"] ]]; then up="${U_UP["$email"]}"; else up=""; fi
if [[ -v U_DOWN["$email"] ]]; then down="${U_DOWN["$email"]}"; else down=""; fi
if [[ -v U_TOTAL["$email"] ]]; then total="${U_TOTAL["$email"]}"; else total=""; fi
up_s="$(bytes_to_gb "$up")"
down_s="$(bytes_to_gb "$down")"
total_s="$(bytes_to_gb "$total")"
qout="$(query_online_ips "$email")"
status="$(sed -n '1p' <<<"$qout")"
ips="$(sed -n '2p' <<<"$qout")"
printf "%-24s %14s %14s %14s %8s %s\n" \
"$email" "$up_s" "$down_s" "$total_s" "$status" "$ips"
done
}
main "$@"
推荐配置定时任务:
TZ=Asia/Shanghai
# 每月8号早上7点重置统计信息
0 7 8 * * /usr/local/bin/xray api statsquery -s=127.0.0.1:8080 -reset=true >/dev/null 2>&1
# 每天早上7点重启日志记录器
0 7 * * * /usr/local/bin/xray api restartlogger -s=127.0.0.1:8080