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

批量提取数千个*.changelog文件中CVE的方案优化问询

问题解答

原方案的可行性

原方案完全可行,但耗时超1小时的核心原因是:shell循环中给每个文件单独调用grep/sort/uniq/awk等外部命令,每次调用都会启动新进程,49000个文件就会产生数万次进程创建/销毁的开销,加上磁盘IO的累积,导致总耗时飙升。

更高效的实现方式

方案1:单进程Awk脚本(最稳定,无并行冲突)

用Awk一次性处理所有文件,全程仅启动一个进程,同时完成单个CVE列表生成和总文件收集,避免反复调用外部工具。

创建提取脚本extract_cves.awk:

BEGIN {
    # 精确匹配CVE格式:CVE-YYYY-NNNN(YYYY为4位年份,NNNN为4位及以上数字)
    cve_pattern = /CVE-[0-9]{4}-[0-9]{4,}/
}

# 处理每个文件的第一行时,提取包名(去掉.changelog后缀)
FNR == 1 {
    pkg = FILENAME
    sub(/\.changelog$/, "", pkg)
    # 用数组存储当前文件的CVE,自动去重
    delete current_cves
}

# 遍历每行,提取所有匹配的CVE
cve_pattern {
    line = $0
    # 一行可能包含多个CVE,循环提取
    while (match(line, cve_pattern, match_result)) {
        cve = match_result[0]
        current_cves[cve] = 1
        # 写入总文件临时记录
        print pkg "\t" cve >> "all_cves.tmp"
        # 截断已匹配的部分,继续查找剩余内容
        line = substr(line, RSTART + RLENGTH)
    }
}

# 当前文件处理完毕,生成单个CVE列表文件
ENDFILE {
    out_file = pkg ".cve"
    print "# CVE List for " pkg > out_file
    for (cve in current_cves) {
        print cve >> out_file
    }
    close(out_file)
}

# 所有文件处理完成后,对总文件去重排序
END {
    close("all_cves.tmp")
    system("sort -u all_cves.tmp > all_cves_pkg_map.txt")
    system("rm -f all_cves.tmp")
}

运行命令:

awk -f extract_cves.awk *.changelog

方案2:并行处理(利用多核,速度更快)

如果机器多核资源充足,用parallel或xargs并行处理多个文件,将总耗时压缩到几分钟级别。

用parallel实现:

# 第一步:并行生成单个文件的CVE列表
parallel --gnu 'grep -o "CVE-[0-9]\{4\}-[0-9]\{4,\}" {} | sort -u > {.}.cve' ::: *.changelog

# 第二步:并行提取所有CVE与包名的映射,去重后生成总文件
parallel --gnu 'grep -o "CVE-[0-9]\{4\}-[0-9]\{4,\}" {} | sort -u | awk -v pkg={} '\''BEGIN{sub(/\.changelog$/,"",pkg)} {print pkg "\t" $0}'\''' ::: *.changelog | sort -u > all_cves_pkg_map.txt

注:--gnu参数适配GNU parallel,若用其他版本可调整;-P N可指定并行进程数(比如-P 16用16核),默认会根据CPU核心数自动调整。

用xargs实现(无parallel时备选):

# 并行生成单个CVE列表
ls *.changelog | xargs -n 1 -P 16 bash -c '
pkg="${1%.changelog}"
grep -o "CVE-[0-9]\{4\}-[0-9]\{4,\}" "$1" | sort -u > "$pkg.cve"
' _

# 并行生成总文件映射
ls *.changelog | xargs -n 1 -P 16 bash -c '
pkg="${1%.changelog}"
grep -o "CVE-[0-9]\{4\}-[0-9]\{4,\}" "$1" | sort -u | awk -v pkg="$pkg" "{print pkg \"\\t\" \$0}"
' _ | sort -u > all_cves_pkg_map.txt

额外优化建议

  • 正则精确匹配:如果有需要,可以把CVE的年份范围限制在合理区间(比如CVE-20[0-9]{2}-[0-9]{4,}),减少无效匹配。
  • 内存文件系统:如果磁盘IO是瓶颈,可将临时文件放在tmpfs(比如/dev/shm),避免磁盘读写延迟。
  • 避免重复扫描:方案1中Awk只扫描一次文件同时完成两类输出,比方案2两次扫描文件更节省IO。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 23:42:31