Bash 使用 gzip 和 bcftools 的脚本 运行 大文件内存不足

Bash script using gzip and bcftools running out of memory with large files

此 bash 脚本旨在成为处理压缩 .vcf 文件的管道的一部分,该文件包含来自多个患者的基因组(这意味着即使压缩文件也很大,例如 3-5GB)。

我的问题是 运行ning 在 运行ning 这个脚本时内存不足。它正在 运行 GCP 高内存虚拟机中。

我希望有一种方法可以优化内存使用,这样就不会失败。我调查了一下,但什么也没发现。

#!/bin/bash

for filename in ./*.vcf.gz; do
    [ -e "$filename" ] || continue 
    name=${filename##*/}
    base=${name%.vcf.gz}
    bcftools query -l "$filename" >> ${base}_list.txt
    for line in `cat ${base}_list.txt`; do 
        bcftools view -s "$line" "$filename" -o ${line}.vcf.gz
        gzip ${line}.vcf 
    done
done

如果您在使用 bcftools query/viewgzip 时 运行 内存不足,请在手册中查找可能减少内存占用的选项。如果是 gzip,您也可以切换到替代实现。您甚至可以考虑完全切换压缩算法(zstd 非常好)。

不过,我感觉问题可能出在 for line in `cat ${base}_list.txt`;。整个文件 ..._list.txt 在循环甚至开始之前就被加载到内存中。此外,以这种方式读取行有各种各样的问题,比如在空白处拆分行,扩展像 * 这样的 glob 等等。改用这个:

while read -r line; do 
    bcftools view -s "$line" "$filename" -o "$line.vcf.gz"
    gzip "$line.vcf"
done < "${base}_list.txt"

顺便说一句:您确定要 bcftools query -l "$filename" >> ${base}_list.txt 追加 。每次执行脚本时,文件 ${base}_list.txt 都会不断增长。考虑使用 > 而不是 >>.
覆盖文件 但是,在那种情况下,您可能根本不需要该文件,因为您可以使用它来代替:

bcftools query -l "$filename" |
while read -r line; do 
    bcftools view -s "$line" "$filename" -o "$line.vcf.gz"
    gzip "$line.vcf"
done

您可以尝试在每个文件上使用 split(变为恒定大​​小),然后 gzip 文件拆分。

https://man7.org/linux/man-pages/man1/split.1.html