CentOS-查询实时报错日志-查询前1天业务报错gz压缩日志
1. 查询实时报错日志
物理路径(带*的放在靠后,或者不用*)
cd /home/logs/java-gz-log-dir && tail -2000f java-gz-log-dir-error.log | grep -ivE '(登录失败|不包含|不合法|不匹配|存在|未在系统中|入参无效|没有【生效中】|找不到|重复|JwtToken|已过期|catalina|token 为空|被踢出|Broken pipe|ErrorPage|Servlet\.service\(\) for servlet \[dispatcherServlet\]|无*数据)' | grep -iE -C 30 '(timeout|PSQLException: ERROR|ERROR|失败|EOFException|SocketException|IOException|sql执行出现异常|不判定为缺失)'
docker版本(带*的放在靠后,或者不用*)
docker logs --tail 20000 --follow java-gz-log-dir | grep -ivE '(登录失败|不包含|不合法|不匹配|存在|未在系统中|入参无效|没有【生效中】|找不到|重复|JwtToken|已过期|catalina|token 为空|被踢出|Broken pipe|ErrorPage|Servlet\.service\(\) for servlet \[dispatcherServlet\]|无*数据)' | grep -iE -C 20 '(timeout|PSQLException: ERROR|ERROR|失败|EOFException|SocketException|IOException|sql执行出现异常|监测点|不判定为缺失)'
2. 查询前1天业务报错gz压缩日志
2.1 简化版
cd /home/logs/java-gz-log-dir && [ -d "/home/logs/java-gz-log-dir/lastDayErrorLog" ] || mkdir /home/logs/java-gz-log-dir/lastDayErrorLog && rm -f /home/logs/java-gz-log-dir/lastDayErrorLog/* && echo "开始复制昨天的错误日志文件" && cp $(ls -t java-gz-log-dir-error.log.*.gz | head -1) lastDayErrorLog && cd ./lastDayErrorLog && echo "开始解压错误日志文件" && gunzip *.gz && echo "开始查找错误日志文件内容" && cat * | grep -ivE '(登录失败|不包含|不合法|不匹配|存在|未在系统中|入参无效|没有【生效中】|找不到|重复|JwtToken|已过期|catalina|token 为空|被踢出|Broken pipe|ErrorPage|Servlet\.service\(\) for servlet \[dispatcherServlet\]|无*数据)' | grep -iE -C 30 '(timeout|PSQLException: ERROR|ERROR|失败|EOFException|SocketException|IOException|sql执行出现异常|监测点|不判定为缺失)' || true && \
echo "查找完成"
2.2 完整版带上下文(不能过滤相邻行错误日志会显示出2条)【不推荐】
#!/bin/bash
clear && \
log_dir="/home/logs/java-gz-log-dir" && \
log_file="java-gz-log-dir-error.log.*.gz" && \
latest_log=$(ls -t $log_dir/$log_file | head -1) && \
if [ -z "$latest_log" ]; then
echo "未找到需要复制的日志文件"
exit 0
fi && \
cd "$log_dir" && \
[ -d "$log_dir/lastDayErrorLog" ] || mkdir "$log_dir/lastDayErrorLog" && \
rm -f "$log_dir"/lastDayErrorLog/* && \
echo "开始复制昨天的错误日志文件: $latest_log" && \
echo "开始复制昨天的错误日志文件: $latest_log" >> "$log_dir/lastDayErrorLog/error_analysis_result.log" && \
cp "$latest_log" "$log_dir/lastDayErrorLog" && \
cd "$log_dir/lastDayErrorLog" && \
echo "开始解压错误日志文件" && \
echo "开始解压错误日志文件" >> "$log_dir/lastDayErrorLog/error_analysis_result.log" && \
gunzip -c *.gz > unzip_file.log || { echo "解压失败"; exit 1; } && \
echo "确认当前文件夹下文件:" && \
echo "确认当前文件夹下文件:" >> "$log_dir/lastDayErrorLog/error_analysis_result.log" && \
ls -lsh >> "$log_dir/lastDayErrorLog/error_analysis_result.log" && \
echo "开始查找错误日志文件内容;$(ls -t ./*)" && \
echo "开始查找错误日志文件内容;$(ls -t ./*)" >> "$log_dir/lastDayErrorLog/error_analysis_result.log" && \
total_lines=$(cat * | wc -l) && \
# 控制打印10次进度日志
print_interval=$((total_lines / 10)) && \
output_file="$log_dir/lastDayErrorLog/error_analysis_result.log" && \
>> "$output_file" && \
echo "请确认以上文件信息,3秒后开始查找..." && \
sleep 3 && \
awk -v total_lines="$total_lines" -v print_interval="$print_interval" '
BEGIN {
context = 100; # 设置上下文为100行
line_count = 0; # 记录当前处理的行数
RED = "\033[38;5;196m"; # 红色
BLUE = "\033[34m"; # 蓝色
RESET = "\033[0m"; # 重置颜色
}
{
# 跳过空白行
if (NF == 0) {
next;
}
# 打印提示信息
if (line_count % print_interval == 0) {
print "继续查找中... 当前行号:", NR, "/ 总行数:", total_lines;
}
line_count++;
# 缓存所有行,不删除任何内容
lines[NR] = $0;
# 忽略不相关的行
if ($0 ~ /登录失败|不包含|不合法|不匹配|存在|未在系统中|入参无效|没有【生效中】|找不到|重复|JwtToken|已过期|catalina|token 为空|被踢出|Broken pipe|ErrorPage|Servlet\.service$$ for servlet $dispatcherServlet$|无*数据/) {
next;
}
# 缓存所有行,不删除任何内【应该提前,不然上下文不连续】
# lines[NR] = $0;
# 匹配目标关键字并记录命中行号
if ($0 ~ /timeout|PSQLException: ERROR|ERROR|失败|EOFException|SocketException|IOException|sql执行出现异常|不判定为缺失/) {
hit_lines[NR] = 1; # 记录命中行号
}
}
END {
# 将命中行号存储到数组中以便排序
n = 0;
for (hit_nr in hit_lines) {
sorted_hits[++n] = hit_nr+0; # 强制转为数值
}
# 手动实现冒泡排序(适用于所有 awk 实现)
for (i = 1; i <= n; i++) {
for (j = i + 1; j <= n; j++) {
if (sorted_hits[i] > sorted_hits[j]) {
temp = sorted_hits[i];
sorted_hits[i] = sorted_hits[j];
sorted_hits[j] = temp;
}
}
}
# 遍历排序后的命中行号,打印上下文
for (i = 1; i <= n; i++) {
hit_nr = sorted_hits[i];
printf("\n\n-----------------------错误序号: %d------------------------------\n", i);
printf("\n\n-----------------------错误序号: %d------------------------------\n", i) >> "'"$output_file"'";
# 打印命中行(红色高亮)
printf("%s命中关键字: 命中行号 %d%s\n", RED, hit_nr, RESET);
printf("%s%s%s\n", RED, lines[hit_nr], RESET); # 打印命中行,使用红色高亮
# 写入文件:命中行
printf("命中关键字: 命中行号 %d\n", hit_nr) >> "'"$output_file"'";
printf("%s\n", lines[hit_nr]) >> "'"$output_file"'";
# 打印上下文范围提示
print (hit_nr > context ? "..." : ""), (hit_nr-context > 0 ? hit_nr-context : 1), "<--命中前后上下文-->", hit_nr+context, "...";
# 写入文件:上下文范围提示
printf((hit_nr > context ? "...\n" : ""), (hit_nr-context > 0 ? hit_nr-context : 1), "<--命中前后上下文-->", hit_nr+context, "...") >> "'"$output_file"'";
# 打印上下文行
for (j = hit_nr-context; j <= hit_nr+context; j++) {
if (j in lines && length(lines[j]) > 0 && j >= 1) { # 确保 j 在有效范围内
if (j == hit_nr) {
# 当前行是命中行,打印红色
printf("%s【当前为命中行,堆栈看下文,行号:%d】 %s%s\n", RED, j, lines[j], RESET);
# 写入文件:命中行上下文
printf("【当前为命中行,堆栈看下文,行号:%d】 %s\n", j, lines[j]) >> "'"$output_file"'";
} else if (lines[j] ~ /cn.jiangjiesheng|otherkeyword/) {
# 当前行包含指定关键词,打印蓝色
printf("%s[行号:%d] %s%s\n", BLUE, j, lines[j], RESET);
# 写入文件:关键词上下文
printf("[行号:%d] %s\n", j, lines[j]) >> "'"$output_file"'";
} else {
# 其他行是上下文行,打印默认颜色
printf("[行号:%d] %s\n", j, lines[j]);
# 写入文件:其他上下文
printf("[行号:%d] %s\n", j, lines[j]) >> "'"$output_file"'";
}
}
}
}
}
' unzip_file.log || true && \
echo " " && \
echo " " >> "$log_dir/lastDayErrorLog/error_analysis_result.log" && \
echo "查找完成,准备删除解压文件" && \
echo "查找完成,准备删除解压文件" >> "$log_dir/lastDayErrorLog/error_analysis_result.log" && \
find "$log_dir/lastDayErrorLog" -maxdepth 1 -type f ! -name '*result*' -exec rm -f {} \; && \
echo "删除解压文件完成,执行ls -lsh结果" && \
echo "删除解压文件完成,执行ls -lsh结果" >> "$log_dir/lastDayErrorLog/error_analysis_result.log" && \
ls -lsh && \
ls -lsh >> "$log_dir/lastDayErrorLog/error_analysis_result.log" && \
echo "是否下载分析结果文件 error_analysis_result.log? 输入 y 确认,其他键跳过【适用XShell,后期可以改成小文件不压缩】: " && \
read user_input && \
if [ "$user_input" = "y" ]; then
tar -zcvf error_analysis_result.log.tar.gz error_analysis_result.log
sz error_analysis_result.log.tar.gz || echo "文件下载失败,请检查环境是否支持 sz 命令。"
else
echo "跳过文件下载。"
fi
2.2 完整版(过滤相邻行错误日志,并显示下文)【推荐】
#!/bin/bash
clear && \
log_dir="/home/logs/java-gz-log-dir" && \
log_file="java-gz-log-dir-error.log.*.gz" && \
latest_log=$(ls -t $log_dir/$log_file | head -1) && \
if [ -z "$latest_log" ]; then
echo "未找到需要复制的日志文件"
exit 0
fi && \
cd "$log_dir" && \
[ -d "$log_dir/lastDayErrorLog" ] || mkdir "$log_dir/lastDayErrorLog" && \
rm -f "$log_dir"/lastDayErrorLog/* && \
echo "开始复制昨天的错误日志文件: $latest_log" && \
echo "开始复制昨天的错误日志文件: $latest_log" >> "$log_dir/lastDayErrorLog/error_analysis_result.log" && \
cp "$latest_log" "$log_dir/lastDayErrorLog" && \
cd "$log_dir/lastDayErrorLog" && \
echo "开始解压错误日志文件" && \
echo "开始解压错误日志文件" >> "$log_dir/lastDayErrorLog/error_analysis_result.log" && \
gunzip -c *.gz > unzip_file.log || { echo "解压失败"; exit 1; } && \
echo "确认当前文件夹下文件:" && \
echo "确认当前文件夹下文件:" >> "$log_dir/lastDayErrorLog/error_analysis_result.log" && \
ls -lsh >> "$log_dir/lastDayErrorLog/error_analysis_result.log" && \
echo "开始查找错误日志文件内容;$(ls -t ./*)" && \
echo "开始查找错误日志文件内容;$(ls -t ./*)" >> "$log_dir/lastDayErrorLog/error_analysis_result.log" && \
total_lines=$(cat * | wc -l) && \
# 控制打印10次进度日志
print_interval=$((total_lines / 10)) && \
output_file="$log_dir/lastDayErrorLog/error_analysis_result.log" && \
>> "$output_file" && \
echo "请确认以上文件信息,3秒后开始查找..." && \
sleep 3 && \
awk -v total_lines="$total_lines" -v print_interval="$print_interval" '
BEGIN {
context = 100; # 设置上下文为100行
line_count = 0; # 记录当前处理的行数
RED = "\033[38;5;196m"; # 红色
BLUE = "\033[34m"; # 蓝色
RESET = "\033[0m"; # 重置颜色
}
{
# 跳过空白行
if (NF == 0) {
next;
}
# 打印提示信息
if (line_count % print_interval == 0) {
print "继续查找中... 当前行号:", NR, "/ 总行数:", total_lines;
}
line_count++;
# 缓存所有行,不删除任何内容
lines[NR] = $0;
# 忽略不相关的行
if ($0 ~ /uni_code_eventid_datatime_starttime_watereventhoursub|uni_monitorid_mn_code_starttime|海康云眸|无设备单元|登录失败|不包含|不合法|不匹配|存在|未在系统中|入参无效|没有【生效中】|找不到|重复|JwtToken|已过期|catalina|token 为空|被踢出|Broken pipe|ErrorPage|Servlet\.service$$ for servlet $dispatcherServlet$|无*数据/) {
next;
}
# 缓存所有行,不删除任何内【应该提前,不然上下文不连续】
# lines[NR] = $0;
# 匹配目标关键字并记录命中行号
if ($0 ~ /timeout|PSQLException: ERROR|ERROR|失败|EOFException|SocketException|IOException|sql执行出现异常|不判定为缺失/) {
hit_lines[NR] = 1; # 记录命中行号
}
}
END {
# 将命中行号存储到数组中以便排序
n = 0;
for (hit_nr in hit_lines) {
sorted_hits[++n] = hit_nr+0; # 强制转为数值
}
# 手动实现冒泡排序(适用于所有 awk 实现)
for (i = 1; i <= n; i++) {
for (j = i + 1; j <= n; j++) {
if (sorted_hits[i] > sorted_hits[j]) {
temp = sorted_hits[i];
sorted_hits[i] = sorted_hits[j];
sorted_hits[j] = temp;
}
}
}
# 遍历排序后的命中行号,打印上下文
last_nr = 0;
err_idx = 0;
for (i = 1; i <= n; i++) {
hit_nr = sorted_hits[i];
err_idx++;
if(hit_nr < last_nr){
continue;
}
printf("\n\n------------------------------------错误序号: %d-------------------------------------------\n", err_idx);
printf("\n\n------------------------------------错误序号: %d-------------------------------------------\n", err_idx) >> "'"$output_file"'";
# 打印命中行(红色高亮)
printf("%s命中关键词: 命中行号 %d%s\n", RED, hit_nr, RESET);
printf("%s%s%s\n", RED, lines[hit_nr], RESET); # 打印命中行,使用红色高亮
# 写入文件:命中行
printf("命中关键词: 命中行号 %d\n", hit_nr) >> "'"$output_file"'";
printf("%s\n", lines[hit_nr]) >> "'"$output_file"'";
# 打印下文
at_counter = 0; # 统计连续以 "at" 开头的行数
for (j = hit_nr + 1; j <= hit_nr + context; j++) {
if (j in lines && length(lines[j]) > 0 && j >= 1) { # 确保 j 在有效范围内
at_counter++; # 增加计数器
last_nr = j;
# 已经超过5行,非 "at" 开头的行(at前面可能有多个空格,后面只有1个空格)
if (at_counter >= 5 && lines[j] !~ /^[[:space:]]*at /) {
printf("-----------------------后面无错误堆栈,只展示最近5条普通日志------------------------------\n", err_idx);
break; # 中止打印,到了堆栈的最后
}
if (lines[j] ~ /cn.jiangjiesheng|com.env|otherkeyword/) {
# 当前行包含指定关键词,打印蓝色
printf("%s[行号:%d] %s%s\n", BLUE, j, lines[j], RESET);
# 写入文件:关键词上下文
printf("[行号:%d] %s\n", j, lines[j]) >> "'"$output_file"'";
} else {
# 打印默认颜色
printf("[行号:%d] %s\n", j, lines[j]);
printf("[行号:%d] %s\n", j, lines[j]) >> "'"$output_file"'";
}
}
}
}
}
' unzip_file.log || true && \
echo " " && \
echo " " >> "$log_dir/lastDayErrorLog/error_analysis_result.log" && \
echo "查找完成,准备删除解压文件" && \
echo "查找完成,准备删除解压文件" >> "$log_dir/lastDayErrorLog/error_analysis_result.log" && \
find "$log_dir/lastDayErrorLog" -maxdepth 1 -type f ! -name '*result*' -exec rm -f {} \; && \
echo "删除解压文件完成,执行ls -lsh结果" && \
echo "删除解压文件完成,执行ls -lsh结果" >> "$log_dir/lastDayErrorLog/error_analysis_result.log" && \
ls -lsh && \
ls -lsh >> "$log_dir/lastDayErrorLog/error_analysis_result.log" && \
echo "是否下载分析结果文件 error_analysis_result.log? 输入 y 确认,其他键跳过【适用XShell,后期可以改成小文件不压缩】: " && \
read user_input && \
if [ "$user_input" = "y" ]; then
tar -zcvf error_analysis_result.log.tar.gz error_analysis_result.log
sz error_analysis_result.log.tar.gz || echo "文件下载失败,请检查环境是否支持 sz 命令。"
else
echo "跳过文件下载。"
fi
2.3 【推荐】看我-在线脚本查询前1天业务报错gz压缩日志:
根据是否需要过滤相邻行的重复日志和只显示下文,选择上面的脚本内容
-- 先判断脚本是否存在
cd /home/logs/java-gz-log-dir && [ -f "analyze_logs.sh" ] && (echo "脚本已存在,直接执行..." && chmod +x analyze_logs.sh && ./analyze_logs.sh) || (echo "脚本不存在,开始下载..." && wget -O analyze_logs.sh --no-check-certificate --backups=0 https://tech.jiangjiesheng.cn/dev/shell/gn/analyze_logs.sh && chmod +x analyze_logs.sh && ./analyze_logs.sh)
-- 不判断脚本是否存在,存在就覆盖
cd /home/logs/java-gz-log-dir && wget -O analyze_logs.sh --no-check-certificate --backups=0 https://tech.jiangjiesheng.cn/dev/shell/gn/analyze_logs.sh && chmod +x analyze_logs.sh && ./analyze_logs.sh
2.4 效果展示
2.5 控制台终端打印的颜色
echo -e "\033[31m红色文字\033[0m"
echo -e "\033[91m亮红色文字\033[0m"
echo -e "\033[38;5;196m非常亮的红色文字\033[0m"
黑色:\033[30m
红色:\033[31m
亮红色文字:\033[91m
非常亮的红色文字:\033[38;5;196m
绿色:\033[32m
黄色:\033[33m
蓝色:\033[34m
紫色:\033[35m
青色:\033[36m
白色:\033[37m
2.6 其他环境快速参考说明
- 压缩文件后缀名为.gz (非.tar.gz),如果不同:
1、log_dir路径修改 2、全局替换java-gz-log-dir, 3、log_file修改: java-gz-log-dir-error.log.*.gz 也要改成具体的xxxx-error.log.*.tar.gz 4、gunzip -c *.gz > unzip_file.log 替换成 tar -xvzf *.tar.gz -C unzip_file.log
- windows编辑的sh脚本要执行去掉换行符:
sed -i 's/\r$//' analyze_logs_*.sh
- 注释#后一定要有空格。
正文到此结束