The -x flag requires exact process name match which doesn't work reliably on OpenWrt/BusyBox. Removed -x from all pgrep calls in: - luci-app-bandwidth-manager - luci-app-secubox-security-threats - luci-app-auth-guardian - luci-app-media-flow - luci-app-vhost-manager - luci-app-network-modes Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
89 lines
3.3 KiB
Bash
89 lines
3.3 KiB
Bash
#!/bin/sh
|
|
#
|
|
# Media Flow Data Collector
|
|
# Collects streaming service data from netifyd and stores in history
|
|
#
|
|
|
|
HISTORY_FILE="/tmp/media-flow-history.json"
|
|
MAX_ENTRIES=1000
|
|
LOCK_FILE="/tmp/media-flow-collector.lock"
|
|
|
|
# Streaming services patterns
|
|
STREAMING_PATTERN="netflix|youtube|disney|primevideo|amazon.*video|twitch|hulu|hbo|vimeo|peacock|paramount|crunchyroll|funimation|spotify|apple.*music|deezer|soundcloud|tidal|pandora|amazon.*music|youtube.*music|zoom|teams|meet|discord|skype|webex|facetime|whatsapp"
|
|
|
|
# Check if already running
|
|
if [ -f "$LOCK_FILE" ]; then
|
|
pid=$(cat "$LOCK_FILE")
|
|
if kill -0 "$pid" 2>/dev/null; then
|
|
exit 0
|
|
fi
|
|
fi
|
|
|
|
echo $$ > "$LOCK_FILE"
|
|
trap "rm -f $LOCK_FILE" EXIT
|
|
|
|
# Check if enabled
|
|
enabled=$(uci -q get media_flow.global.enabled 2>/dev/null || echo "1")
|
|
[ "$enabled" != "1" ] && exit 0
|
|
|
|
# Check if netifyd is running
|
|
pgrep netifyd > /dev/null 2>&1 || exit 0
|
|
|
|
# Initialize history file
|
|
[ ! -f "$HISTORY_FILE" ] && echo '[]' > "$HISTORY_FILE"
|
|
|
|
# Get current flows from netifyd
|
|
if [ -f /var/run/netifyd/status.json ]; then
|
|
timestamp=$(date -Iseconds)
|
|
|
|
# Extract streaming flows and format as history entries
|
|
new_entries=$(jq -c --arg ts "$timestamp" '
|
|
.flows // [] |
|
|
[.[] |
|
|
select(.detected_application != null and .detected_application != "") |
|
|
select(.detected_application | test("'"$STREAMING_PATTERN"'"; "i")) |
|
|
{
|
|
timestamp: $ts,
|
|
app: .detected_application,
|
|
client: (.local_ip // .src_ip // "unknown"),
|
|
bandwidth: (if .total_packets > 0 and .duration > 0 then
|
|
((.total_bytes * 8) / 1000 / .duration) | floor
|
|
else 0 end),
|
|
duration: (.duration // 0 | floor),
|
|
quality: (if .total_packets > 0 and .duration > 0 then
|
|
(if ((.total_bytes * 8) / 1000 / .duration) < 1000 then "SD"
|
|
elif ((.total_bytes * 8) / 1000 / .duration) < 3000 then "HD"
|
|
elif ((.total_bytes * 8) / 1000 / .duration) < 8000 then "FHD"
|
|
else "4K" end)
|
|
else "SD" end),
|
|
category: (if (.detected_application | test("netflix|youtube|disney|primevideo|twitch|hulu|hbo|vimeo"; "i")) then "video"
|
|
elif (.detected_application | test("spotify|apple.*music|deezer|soundcloud|tidal"; "i")) then "audio"
|
|
elif (.detected_application | test("zoom|teams|meet|discord|skype|webex"; "i")) then "visio"
|
|
else "other" end),
|
|
bytes: (.total_bytes // 0)
|
|
}
|
|
] |
|
|
# Only include flows with significant duration (> 10 seconds)
|
|
[.[] | select(.duration > 10)]
|
|
' /var/run/netifyd/status.json 2>/dev/null)
|
|
|
|
# If we have new entries, merge with history
|
|
if [ -n "$new_entries" ] && [ "$new_entries" != "[]" ] && [ "$new_entries" != "null" ]; then
|
|
# Merge and deduplicate (by client+app combination within same minute)
|
|
jq -c --argjson new "$new_entries" '
|
|
. + $new |
|
|
# Keep only last MAX_ENTRIES
|
|
.[-'"$MAX_ENTRIES"':]
|
|
' "$HISTORY_FILE" > "${HISTORY_FILE}.tmp" 2>/dev/null && mv "${HISTORY_FILE}.tmp" "$HISTORY_FILE"
|
|
fi
|
|
fi
|
|
|
|
# Clean old entries based on retention (days)
|
|
retention=$(uci -q get media_flow.global.history_retention 2>/dev/null || echo "7")
|
|
if [ "$retention" -gt 0 ] 2>/dev/null; then
|
|
cutoff_date=$(date -d "$retention days ago" -Iseconds 2>/dev/null || date -Iseconds)
|
|
jq -c --arg cutoff "$cutoff_date" '[.[] | select(.timestamp >= $cutoff)]' "$HISTORY_FILE" > "${HISTORY_FILE}.tmp" 2>/dev/null && mv "${HISTORY_FILE}.tmp" "$HISTORY_FILE"
|
|
fi
|
|
|
|
exit 0
|