-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathlogger.sh
More file actions
480 lines (391 loc) · 11.5 KB
/
Copy pathlogger.sh
File metadata and controls
480 lines (391 loc) · 11.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
#!/bin/bash
#
# UART Logger and Monitor
# Capture, filter, and analyze serial port output
#
set -euo pipefail
# Configuration
UART_PORT="${UART_PORT:-/dev/ttyUSB0}"
BAUD_UART="${BAUD_UART:-115200}"
LOG_FILE="${LOG_FILE:-uart_log_$(date +%Y%m%d_%H%M%S).log}"
OUTPUT_DIR="${OUTPUT_DIR:-./uart_logs}"
FILTER="${FILTER:-}"
TIMESTAMP="${TIMESTAMP:-1}"
HEX_MODE="${HEX_MODE:-0}"
STATS="${STATS:-0}"
# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
MAGENTA='\033[0;35m'
NC='\033[0m'
# Statistics
declare -A STATS_DATA=(
[bytes]=0
[lines]=0
[errors]=0
[warnings]=0
)
# Logging
log() {
local level="$1"
shift
local msg="$*"
case "$level" in
ERROR) echo -e "${RED}[ERROR]${NC} $msg" >&2 ;;
WARN) echo -e "${YELLOW}[WARN]${NC} $msg" ;;
INFO) echo -e "${GREEN}[INFO]${NC} $msg" ;;
DEBUG) echo -e "${BLUE}[DEBUG]${NC} $msg" ;;
esac
}
# Initialize output directory
init_output() {
mkdir -p "$OUTPUT_DIR"
LOG_FILE="$OUTPUT_DIR/$(basename "$LOG_FILE")"
log INFO "Output: $LOG_FILE"
}
# Initialize UART
init_uart() {
log INFO "Initializing UART on $UART_PORT at $BAUD_UART baud"
if [ ! -e "$UART_PORT" ]; then
log ERROR "Port $UART_PORT not found"
return 1
fi
if [ ! -r "$UART_PORT" ]; then
log ERROR "Cannot read from $UART_PORT (permission denied)"
return 1
fi
# Kill processes using the port
if fuser "$UART_PORT" 2>/dev/null; then
local pids=$(fuser "$UART_PORT" 2>/dev/null)
log WARN "Killing processes using port: $pids"
kill -9 $pids 2>/dev/null || true
sleep 1
fi
# Configure port
stty -F "$UART_PORT" \
$BAUD_UART \
raw \
-echo \
cs8 \
-parenb \
-cstopb 2>/dev/null
log INFO "UART initialized successfully"
return 0
}
# Format line with timestamp
format_line() {
local line="$1"
local output=""
# Add timestamp
if [ "$TIMESTAMP" -eq 1 ]; then
output="[$(date '+%Y-%m-%d %H:%M:%S.%3N')] "
fi
# Convert to hex if needed
if [ "$HEX_MODE" -eq 1 ]; then
output+="$(echo -n "$line" | xxd -p -c 0)"
else
output+="$line"
fi
echo "$output"
}
# Colorize output based on content
colorize_line() {
local line="$1"
# Check for error patterns
if echo "$line" | grep -qiE "error|fail|fatal|panic"; then
echo -e "${RED}${line}${NC}"
((STATS_DATA[errors]++))
# Check for warning patterns
elif echo "$line" | grep -qiE "warn|warning|alert"; then
echo -e "${YELLOW}${line}${NC}"
((STATS_DATA[warnings]++))
# Check for success patterns
elif echo "$line" | grep -qiE "success|ok|done|complete"; then
echo -e "${GREEN}${line}${NC}"
# Check for info patterns
elif echo "$line" | grep -qiE "info|debug|trace"; then
echo -e "${CYAN}${line}${NC}"
else
echo "$line"
fi
}
# Apply filter
apply_filter() {
local line="$1"
if [ -z "$FILTER" ]; then
echo "$line"
return 0
fi
if echo "$line" | grep -qE "$FILTER"; then
echo "$line"
return 0
fi
return 1
}
# Monitor and log
monitor_uart() {
log INFO "Starting UART monitor (Ctrl+C to stop)"
log INFO "Logging to: $LOG_FILE"
if [ -n "$FILTER" ]; then
log INFO "Filter: $FILTER"
fi
echo -e "${CYAN}=== UART Monitor ===${NC}"
echo -e "${CYAN}Port: $UART_PORT @ $BAUD_UART baud${NC}"
echo -e "${CYAN}===================${NC}"
echo
# Open log file
exec 3>>"$LOG_FILE"
# Main monitoring loop
while IFS= read -r line; do
((STATS_DATA[bytes]+=${#line}))
((STATS_DATA[lines]++))
# Format line
local formatted=$(format_line "$line")
# Apply filter
if ! apply_filter "$formatted" >/dev/null; then
continue
fi
# Write to log file
echo "$formatted" >&3
# Colorize and display
colorize_line "$formatted"
done < "$UART_PORT"
# Close log file
exec 3>&-
}
# Capture for duration
capture_duration() {
local duration="$1"
log INFO "Capturing for ${duration}s..."
timeout "$duration" monitor_uart || true
log INFO "Capture completed"
}
# Analyze log file
analyze_log() {
local log_file="$1"
if [ ! -f "$log_file" ]; then
log ERROR "Log file not found: $log_file"
return 1
fi
log INFO "Analyzing log: $log_file"
echo
# Basic statistics
local total_lines=$(wc -l < "$log_file")
local total_bytes=$(stat -f%z "$log_file" 2>/dev/null || stat -c%s "$log_file" 2>/dev/null)
local errors=$(grep -ciE "error|fail|fatal|panic" "$log_file" || echo 0)
local warnings=$(grep -ciE "warn|warning|alert" "$log_file" || echo 0)
echo -e "${CYAN}=== Log Analysis ===${NC}"
echo "File: $log_file"
echo "Size: $(numfmt --to=iec-i --suffix=B $total_bytes 2>/dev/null || echo "$total_bytes bytes")"
echo "Lines: $total_lines"
echo -e "${RED}Errors: $errors${NC}"
echo -e "${YELLOW}Warnings: $warnings${NC}"
echo
# Most common patterns
echo -e "${CYAN}=== Top 10 Most Common Lines ===${NC}"
sort "$log_file" | uniq -c | sort -rn | head -10
echo
# Time analysis (if timestamps present)
if grep -q '^\[20[0-9][0-9]-' "$log_file"; then
echo -e "${CYAN}=== Time Analysis ===${NC}"
local first_ts=$(grep -oE '^\[[0-9: -]+\]' "$log_file" | head -1 | tr -d '[]')
local last_ts=$(grep -oE '^\[[0-9: -]+\]' "$log_file" | tail -1 | tr -d '[]')
echo "First entry: $first_ts"
echo "Last entry: $last_ts"
echo
fi
# Error summary
if [ $errors -gt 0 ]; then
echo -e "${RED}=== Error Summary ===${NC}"
grep -iE "error|fail|fatal|panic" "$log_file" | tail -20
echo
fi
}
# Show live statistics
show_stats() {
local interval="${1:-5}"
log INFO "Displaying live statistics (update every ${interval}s)"
# Start monitoring in background
monitor_uart &
local monitor_pid=$!
# Statistics display loop
while kill -0 $monitor_pid 2>/dev/null; do
sleep "$interval"
clear
echo -e "${CYAN}=== Live UART Statistics ===${NC}"
echo "Port: $UART_PORT @ $BAUD_UART baud"
echo "Time: $(date '+%Y-%m-%d %H:%M:%S')"
echo
echo "Lines: ${STATS_DATA[lines]}"
echo "Bytes: ${STATS_DATA[bytes]} ($(numfmt --to=iec-i --suffix=B ${STATS_DATA[bytes]} 2>/dev/null))"
echo -e "${RED}Errors: ${STATS_DATA[errors]}${NC}"
echo -e "${YELLOW}Warnings: ${STATS_DATA[warnings]}${NC}"
echo
echo "Rate: $((STATS_DATA[bytes] / (interval * SECONDS / interval))) bytes/sec"
echo
echo "Press Ctrl+C to stop"
done
}
# Tail mode - like tail -f
tail_mode() {
log INFO "Tail mode - following UART output"
while IFS= read -r line; do
colorize_line "$(format_line "$line")"
done < "$UART_PORT"
}
# Grep mode - filter and display
grep_mode() {
local pattern="$1"
log INFO "Grep mode - filtering for: $pattern"
while IFS= read -r line; do
if echo "$line" | grep -qE "$pattern"; then
colorize_line "$(format_line "$line")"
fi
done < "$UART_PORT"
}
# Display usage
usage() {
cat << EOF
Usage: $0 [OPTIONS] COMMAND [ARGS]
UART Logger and Monitor
Commands:
monitor Start monitoring (default)
capture SECONDS Capture for specified duration
analyze FILE Analyze existing log file
stats [INTERVAL] Show live statistics
tail Tail mode (follow output)
grep PATTERN Filter output by pattern
Options:
-p PORT Serial port (default: $UART_PORT)
-b BAUD Baud rate (default: $BAUD_UART)
-o FILE Output log file (default: $LOG_FILE)
-d DIR Output directory (default: $OUTPUT_DIR)
-f PATTERN Filter pattern (regex)
-x Hex mode (display as hex)
-n No timestamps
-s Enable statistics
-h Show this help
Environment Variables:
UART_PORT Override default port
BAUD_UART Override default baud rate
LOG_FILE Override default log file
OUTPUT_DIR Override default output directory
FILTER Default filter pattern
TIMESTAMP Enable/disable timestamps (1/0)
HEX_MODE Enable/disable hex mode (1/0)
Examples:
# Simple monitoring
$0 monitor
# Capture for 60 seconds
$0 capture 60
# Monitor with filter
$0 -f "ERROR|WARN" monitor
# Hex mode
$0 -x monitor
# Live statistics
$0 stats 5
# Tail mode
$0 tail
# Grep mode
$0 grep "temperature"
# Analyze existing log
$0 analyze uart_log.txt
# Custom output
$0 -o mylog.txt -d /tmp/logs monitor
Features:
- Automatic colorization of errors/warnings/success
- Timestamp support with millisecond precision
- Hex dump mode for binary data
- Live statistics and analysis
- Pattern filtering
- Log file analysis
EOF
exit 0
}
# Parse arguments
parse_args() {
while getopts "p:b:o:d:f:xnsth" opt; do
case "$opt" in
p) UART_PORT="$OPTARG" ;;
b) BAUD_UART="$OPTARG" ;;
o) LOG_FILE="$OPTARG" ;;
d) OUTPUT_DIR="$OPTARG" ;;
f) FILTER="$OPTARG" ;;
x) HEX_MODE=1 ;;
n) TIMESTAMP=0 ;;
s) STATS=1 ;;
h) usage ;;
*) usage ;;
esac
done
shift $((OPTIND-1))
COMMAND="${1:-monitor}"
shift 2>/dev/null || true
ARGS=("$@")
}
# Cleanup
cleanup() {
log INFO "Stopping monitor..."
if [ "$STATS" -eq 1 ]; then
echo
echo -e "${CYAN}=== Final Statistics ===${NC}"
echo "Lines: ${STATS_DATA[lines]}"
echo "Bytes: ${STATS_DATA[bytes]}"
echo "Errors: ${STATS_DATA[errors]}"
echo "Warnings: ${STATS_DATA[warnings]}"
fi
exit 0
}
trap cleanup INT TERM
# Main
main() {
parse_args "$@"
init_output
log INFO "=== UART Logger Started ==="
log INFO "Port: $UART_PORT | Baud: $BAUD_UART"
case "$COMMAND" in
monitor)
init_uart || exit 1
monitor_uart
;;
capture)
if [ ${#ARGS[@]} -eq 0 ]; then
log ERROR "No duration specified"
exit 1
fi
init_uart || exit 1
capture_duration "${ARGS[0]}"
;;
analyze)
if [ ${#ARGS[@]} -eq 0 ]; then
log ERROR "No log file specified"
exit 1
fi
analyze_log "${ARGS[0]}"
;;
stats)
init_uart || exit 1
show_stats "${ARGS[0]:-5}"
;;
tail)
init_uart || exit 1
tail_mode
;;
grep)
if [ ${#ARGS[@]} -eq 0 ]; then
log ERROR "No pattern specified"
exit 1
fi
init_uart || exit 1
grep_mode "${ARGS[0]}"
;;
*)
log ERROR "Unknown command: $COMMAND"
usage
;;
esac
}
main "$@"