You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用parallel命令异步解析大日志文件的脚本问题求助

日志批量排查脚本问题排查与修复

背景信息

日志格式

日志每行格式如下:

[01/18/2024 23:59:58 job100305.mydomain.com dbmy.db18.import 3823039] {"PREFIX":"ZaoBzgriEBMAIglWABgEZg","LEVEL":"info","MESSAGE":"received\n"}
[01/18/2024 23:59:58 job100129.mydomain.com db.db5.my-route 2423585] {"ELAPSED":"0.036","PREFIX":"ZaoBzgriFH4AJIMBAALvAw","LEVEL":"info","MESSAGE":"finished in 0.036\n","ROUTINGKEY":"mydomain11016.Interface.DistributeManager.InboundDistributor.RemotePutMessageBatch"}

日志文件命名规则

按小时拆分,单个文件约4TB:

mylog-2024-01-19_00001
mylog-2024-01-19_00002
...
mylog-2024-01-19_00023

集群配置

可无密码访问dev1.mydomain.com至dev10.mydomain.com共10台服务器,家目录下sshloginfile配置每台服务器运行4线程:

4/ dev1.mydomain.com
4/ dev2.mydomain.com
...
4/ dev10.mydomain.com

需求

编写Shell脚本用parallel异步执行grep,满足:

  • 每个日志文件对应一个parallel进程
  • 所有结果汇总到单个文件
  • 单日日志由同一台dev服务器处理
  • 支持解析指定日期范围内的所有日志
  • 每台服务器同时运行4线程

问题:自行编写的脚本无输出

用户脚本如下:

#!/bin/bash

log_directory="/path/to/log/files" directory
start_date="2024-01-19"
end_date="2024-01-19"
output_file="parsed_logs.txt"

for log_file in $(ls $log_directory/mylog-$start_date*); do
    date_part=$(echo $log_file | grep -oP '\d{4}-\d{2}-\d{2}')

    if [[ "$date_part" >= "$start_date" && "$date_part" <= "$end_date" ]]; then
        dev_server=$(grep "$date_part" ~/sshlogins | awk '{print $2}')

        parallel --sshloginfile ~/sshlogins -S $dev_server -j4 "grep 'your_search_pattern' {} >> $output_file" ::: $log_file
    fi
done

echo "Parsing completed. Results are stored in $output_file."

问题排查与修复

1. 语法错误:变量定义冗余

第一行变量定义多了无关的directory,应修正为:

log_directory="/path/to/log/files"

2. 日期-服务器映射逻辑缺失

脚本中用grep "$date_part" ~/sshlogins匹配服务器,但sshloginfile里没有日期信息,无法实现单日日志绑定固定服务器的需求。可以通过日期哈希取模的方式分配:

# 计算日期对应的服务器索引(1-10)
date_hash=$(echo "$date_part" | md5sum | cut -c1-2)
server_index=$((16#$date_hash % 10 + 1))
dev_server="dev${server_index}.mydomain.com"

3. 远程输出路径错误

原脚本中远程执行grep时直接追加到$output_file,会把结果写到远程服务器的对应路径,而非本地。需要将远程grep的结果传回本地追加:

parallel --sshloginfile ~/sshlogins -S $dev_server -j4 "grep 'your_search_pattern' {}" ::: $log_file >> $output_file

4. 遍历文件方式不可靠

用ls遍历文件会遇到文件名含空格等特殊字符的问题,改用通配符安全遍历:

for log_file in "${log_directory}"/mylog-*; do
    # 提取日期部分
    date_part=$(basename "$log_file" | grep -oP '\d{4}-\d{2}-\d{2}')
    # ...后续逻辑
done

5. Parallel参数冗余

--sshloginfile已经包含每台服务器的线程数配置,无需重复指定-j4,保持参数一致即可。


修正后的完整脚本

#!/bin/bash

log_directory="/path/to/log/files"
start_date="2024-01-19"
end_date="2024-01-19"
output_file="parsed_logs.txt"
search_pattern="your_search_pattern"

# 清空输出文件(可选,按需保留)
> "$output_file"

# 遍历所有日志文件
for log_file in "${log_directory}"/mylog-*; do
    # 提取日期部分
    date_part=$(basename "$log_file" | grep -oP '\d{4}-\d{2}-\d{2}')
    if [[ -z "$date_part" ]]; then
        continue
    fi

    # 判断日期是否在指定范围内
    if [[ "$date_part" < "$start_date" || "$date_part" > "$end_date" ]]; then
        continue
    fi

    # 给单日日志分配固定服务器(哈希取模绑定10台机器)
    date_hash=$(echo "$date_part" | md5sum | cut -c1-2)
    server_index=$((16#$date_hash % 10 + 1))
    dev_server="dev${server_index}.mydomain.com"

    # 用parallel在指定服务器执行grep,结果追加到本地输出文件
    parallel --sshloginfile ~/sshlogins -S "$dev_server" "grep '$search_pattern' {}" ::: "$log_file" >> "$output_file"
done

echo "Parsing completed. Results are stored in $output_file."

内容的提问来源于stack exchange,提问作者tuxian

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 21:05:31