在太多文件上运行命令

问题描述 投票:0回答:1

我想加密和解密大文件(想像20m行)的文本。我使用的加密服务最多只能加密64kb。出于这个问题的目的,假设我们坚持使用此服务。

我的解决方案是将巨大的文件分割为64kb的块,对所有文件进行并行加密,然后将加密的部分放入tar.gz。每个部分都编号为part-xxx,以确保我可以恢复原始文件。在解密时,我解压缩,并行解密每个部分并按顺序合并结果。

有趣的部分:当我在足够大的文件上执行最后一部分时,发生以下情况之一:

  1. tmux会话终止,我退出了。没有日志,什么都没有。

  2. 我明白了:

/home/estergiadis/kms/decrypt.sh: line 45: /usr/bin/find: Argument list too long
/home/estergiadis/kms/decrypt.sh: line 46: /bin/rm: Argument list too long

我尝试了几种基于xargs的解决方案,但没有运气。这是有趣的代码:

echo "Decrypting chunks in parallel."
# -1 -f in ls helped me go from scenario 1 to scenario 2 above. 
# Makes sense since I don't need sorting at this stage.
ls -1 -f part-* | xargs -I % -P 32 bash -c "gcloud kms decrypt --ciphertext-file % --plaintext-file ${OUTPUT}.%"

# Best case scenario, we die here
find $OUTPUT.part-* | xargs cat > $OUTPUT
rm $OUTPUT.part-*

更有趣的是:当find和rm报告问题时,我可以进入temp文件夹,包括所有部分,自己运行完全相同的命令,一切正常。

如果很重要,所有这些都发生在安装有RAM的文件系统中。但是,RAM可能不是问题:我在具有256GB RAM的计算机上,所涉及的文件占用1-2GB,htop的使用率从未超过10%。

encryption xargs concurrent-processing
1个回答
0
投票

您的问题是这些:

ls -1 -f part-* | ...
find $OUTPUT.part-* | ...
rm $OUTPUT.part-*

如果部件过多(part-*等),shell扩展的文件名将导致命令中包含太多参数,或者您可能超过了最大命令长度。

find + xargs使您可以克服这一点。您可以使用以下命令替换使用glob列出当前目录中文件的任何命令,例如:

find . -name GLOB -print -o ! -path . -prune | xargs CMD

-o ! -path . -prune告诉find不要进入子目录。 xargs确保生成的命令行不超过最大参数或行数限制。

因此您可以对三行进行操作:

globwrap(){
    glob="$1"
    shift

    find . -name "$glob" -print -o ! -path . -prune |\
    sed 's/^..//' |\
    xargs "$@" # defaults to echo if no command given
}

globwrap 'part-*' | ...
globwrap "$OUTPUT"'.part-*' | ...
globwrap "$OUTPUT"'.part-*' rm

单引号可防止外壳扩展我们试图传递给find的glob。

[sed删除要附加到每个文件名的./

请注意,前两种情况不再需要原始的lsfind

© www.soinside.com 2019 - 2024. All rights reserved.