mirror of
https://gh.wpcy.net/https://github.com/CaptainCore/do.git
synced 2026-04-17 21:52:19 +08:00
255 lines
No EOL
8.8 KiB
Bash
255 lines
No EOL
8.8 KiB
Bash
# ----------------------------------------------------
|
|
# Monitors server access logs in real-time.
|
|
# ----------------------------------------------------
|
|
function monitor_traffic() {
|
|
local limit_arg="$1"
|
|
local process_from_now="$2"
|
|
|
|
if ! setup_gum; then
|
|
echo "Aborting monitor: gum setup failed." >&2
|
|
return 1
|
|
fi
|
|
|
|
# --- Configuration ---
|
|
local limit=${limit_arg:-25}
|
|
local log="$HOME/logs/access.log"
|
|
local initial_lines_to_process=1 # How many lines to look back initially (only used with --now)
|
|
# --- End Configuration ---
|
|
|
|
if [ ! -f "$log" ]; then
|
|
echo "Error: Log file not found at $log" >&2
|
|
exit 1
|
|
fi
|
|
|
|
# --- Initial Setup ---
|
|
local start_line=1 # Default: start from the beginning
|
|
|
|
if [ "$process_from_now" = true ]; then
|
|
echo "Processing from near the end (--now specified)." >&2
|
|
local initial_log_count; initial_log_count=$(wc -l < "$log")
|
|
local calculated_start=$((initial_log_count - initial_lines_to_process + 1))
|
|
|
|
if [ $calculated_start -gt 1 ]; then
|
|
start_line=$calculated_start
|
|
else
|
|
start_line=1
|
|
fi
|
|
else
|
|
echo "Processing from the beginning of the log (line 1)." >&2
|
|
fi
|
|
|
|
echo "Starting analysis from line: $start_line | Top hits limit: $limit" >&2
|
|
# --- End Initial Setup ---
|
|
|
|
trap "echo; echo 'Monitoring stopped.'; exit 0" INT
|
|
sleep 2 # Give user time to read initial messages
|
|
|
|
while true; do
|
|
local current_log_count; current_log_count=$(wc -l < "$log")
|
|
|
|
if [ "$current_log_count" -lt "$start_line" ]; then
|
|
echo "Warning: Log file appears to have shrunk or rotated. Resetting start line to 1." >&2
|
|
start_line=1
|
|
sleep 1
|
|
current_log_count=$(wc -l < "$log")
|
|
if [ "$current_log_count" -lt 1 ]; then
|
|
echo "Log file is empty or unreadable after reset. Waiting..." >&2
|
|
sleep 5
|
|
continue
|
|
fi
|
|
fi
|
|
|
|
local actual_lines_processed=$((current_log_count - start_line + 1))
|
|
if [ $actual_lines_processed -lt 0 ]; then
|
|
actual_lines_processed=0
|
|
fi
|
|
|
|
local overview_header="PHP Workers,Log File,Processed,From Time,To Time\n"
|
|
local overview_data=""
|
|
local php_workers; php_workers=$(ps -eo pid,uname,comm,%cpu,%mem,time --sort=time --no-headers | grep '[p]hp-fpm' | grep -v 'root' | wc -l)
|
|
|
|
local first_line_time; first_line_time=$(sed -n "${start_line}p" "$log" | awk -F'[][]' '{print $2}' | head -n 1)
|
|
[ -z "$first_line_time" ] && first_line_time="N/A"
|
|
|
|
local last_line_time; last_line_time=$(tail -n 1 "$log" | awk -F'[][]' '{print $2}' | head -n 1)
|
|
[ -z "$last_line_time" ] && last_line_time="N/A"
|
|
|
|
overview_data+="$php_workers,$log,$actual_lines_processed,$first_line_time,$last_line_time\n"
|
|
local output_header="Hits,IP Address,Status Code,Last User Agent\n"
|
|
local output_data=""
|
|
|
|
local top_combinations; top_combinations=$(timeout 10s sed -n "$start_line,\$p" "$log" | \
|
|
awk '{print $2 " " $8}' | \
|
|
sort | \
|
|
uniq -c | \
|
|
sort -nr | \
|
|
head -n "$limit")
|
|
|
|
if [ -z "$top_combinations" ]; then
|
|
output_data+="0,No new data,-,\"N/A\"\n"
|
|
else
|
|
while IFS= read -r line; do
|
|
line=$(echo "$line" | sed 's/^[ \t]*//;s/[ \t]*$//')
|
|
local count ip status_code
|
|
read -r count ip status_code <<< "$line"
|
|
|
|
if ! [[ "$count" =~ ^[0-9]+$ ]] || [[ -z "$ip" ]] || ! [[ "$status_code" =~ ^[0-9]+$ ]]; then
|
|
continue
|
|
fi
|
|
|
|
local ip_user_agent; ip_user_agent=$(timeout 2s sed -n "$start_line,\$p" "$log" | grep " $ip " | tail -n 1 | awk -F\" '{print $6}' | cut -c 1-100)
|
|
ip_user_agent=${ip_user_agent//,/}
|
|
ip_user_agent=${ip_user_agent//\"/}
|
|
|
|
[ -z "$ip_user_agent" ] && ip_user_agent="-"
|
|
|
|
output_data+="$count,$ip,$status_code,\"$ip_user_agent\"\n"
|
|
done < <(echo -e "$top_combinations")
|
|
fi
|
|
|
|
clear
|
|
echo "--- Overview (Lines $start_line - $current_log_count | Total: $actual_lines_processed) ---"
|
|
echo -e "$overview_header$overview_data" | "$GUM_CMD" table --print
|
|
echo
|
|
echo "--- Top $limit IP/Status Hits (Lines $start_line - $current_log_count) ---"
|
|
echo -e "$output_header$output_data" | "$GUM_CMD" table --print
|
|
|
|
sleep 2
|
|
done
|
|
}
|
|
|
|
# ----------------------------------------------------
|
|
# Monitors access and error logs for HTTP 500 and PHP fatal errors.
|
|
# ----------------------------------------------------
|
|
function monitor_errors() {
|
|
if ! setup_gum; then
|
|
echo "Aborting monitor: gum setup failed." >&2
|
|
return 1
|
|
fi
|
|
|
|
# --- Find Log Files ---
|
|
local access_log_path=""
|
|
if [ -f "$HOME/logs/access.log" ]; then
|
|
access_log_path="$HOME/logs/access.log"
|
|
elif [ -f "logs/access.log" ]; then
|
|
access_log_path="logs/access.log"
|
|
elif [ -f "../logs/access.log" ]; then
|
|
access_log_path="../logs/access.log"
|
|
fi
|
|
|
|
local error_log_path=""
|
|
if [ -f "$HOME/logs/error.log" ]; then
|
|
error_log_path="$HOME/logs/error.log"
|
|
elif [ -f "logs/error.log" ]; then
|
|
error_log_path="logs/error.log"
|
|
elif [ -f "../logs/error.log" ]; then
|
|
error_log_path="../logs/error.log"
|
|
fi
|
|
|
|
local files_to_monitor=()
|
|
if [ -n "$access_log_path" ]; then
|
|
echo "Checking for 500 errors in: $access_log_path" >&2
|
|
files_to_monitor+=("$access_log_path")
|
|
fi
|
|
if [ -n "$error_log_path" ]; then
|
|
echo "Checking for Fatal errors in: $error_log_path" >&2
|
|
files_to_monitor+=("$error_log_path")
|
|
fi
|
|
|
|
if [ ${#files_to_monitor[@]} -eq 0 ]; then
|
|
echo "No log files found in standard locations (~/logs/, logs/, ../logs/)" >&2
|
|
return 1
|
|
fi
|
|
|
|
echo "Streaming errors from specified logs..." >&2
|
|
echo "(Press Ctrl+C to stop)" >&2
|
|
|
|
# --- Real-time Stream using `tail -F` ---
|
|
tail -q -n 0 -F "${files_to_monitor[@]}" | while read -r line; do
|
|
# Skip empty lines that might come from the pipe
|
|
if [ -z "$line" ]; then
|
|
continue
|
|
fi
|
|
|
|
# Check for the most specific term first ("Fatal") before less specific terms.
|
|
if [[ "$line" == *"Fatal"* ]]; then
|
|
"$GUM_CMD" log --level error "$line"
|
|
elif [[ "$line" == *" 500 "* ]]; then
|
|
"$GUM_CMD" log --level error "$line"
|
|
fi
|
|
done
|
|
}
|
|
|
|
# ----------------------------------------------------
|
|
# Tails the access log for a clean, real-time view.
|
|
# ----------------------------------------------------
|
|
function monitor_access_log() {
|
|
if ! setup_gum; then
|
|
echo "Aborting monitor: gum setup failed." >&2
|
|
return 1
|
|
fi
|
|
|
|
# --- Find Log File ---
|
|
local access_log_path=""
|
|
if [ -f "$HOME/logs/access.log" ]; then
|
|
access_log_path="$HOME/logs/access.log"
|
|
elif [ -f "logs/access.log" ]; then
|
|
access_log_path="logs/access.log"
|
|
elif [ -f "../logs/access.log" ]; then
|
|
access_log_path="../logs/access.log"
|
|
fi
|
|
|
|
if [ -z "$access_log_path" ]; then
|
|
echo "No access.log file found in standard locations (~/logs/, logs/, ../logs/)" >&2
|
|
return 1
|
|
fi
|
|
|
|
echo "Streaming log: $access_log_path" >&2
|
|
echo "(Press Ctrl+C to stop)" >&2
|
|
|
|
# --- Real-time Stream using `tail -F` ---
|
|
tail -n 50 -F "$access_log_path" | while read -r line; do
|
|
# Skip empty lines
|
|
if [ -z "$line" ]; then
|
|
continue
|
|
fi
|
|
"$GUM_CMD" log --level info "$line"
|
|
done
|
|
}
|
|
|
|
# ----------------------------------------------------
|
|
# Tails the error log for a clean, real-time view.
|
|
# ----------------------------------------------------
|
|
function monitor_error_log() {
|
|
if ! setup_gum; then
|
|
echo "Aborting monitor: gum setup failed." >&2
|
|
return 1
|
|
fi
|
|
|
|
# --- Find Log File ---
|
|
local error_log_path=""
|
|
if [ -f "$HOME/logs/error.log" ]; then
|
|
error_log_path="$HOME/logs/error.log"
|
|
elif [ -f "logs/error.log" ]; then
|
|
error_log_path="logs/error.log"
|
|
elif [ -f "../logs/error.log" ]; then
|
|
error_log_path="../logs/error.log"
|
|
fi
|
|
|
|
if [ -z "$error_log_path" ]; then
|
|
echo "No error.log file found in standard locations (~/logs/, logs/, ../logs/)" >&2
|
|
return 1
|
|
fi
|
|
|
|
echo "Streaming log: $error_log_path" >&2
|
|
echo "(Press Ctrl+C to stop)" >&2
|
|
|
|
# --- Real-time Stream using `tail -F` ---
|
|
tail -n 50 -F "$error_log_path" | while read -r line; do
|
|
# Skip empty lines
|
|
if [ -z "$line" ]; then
|
|
continue
|
|
fi
|
|
"$GUM_CMD" log --level error "$line"
|
|
done
|
|
} |