【问题标题】:Using GNU Parallel With Split使用 GNU 并行拆分
【发布时间】:2013-02-15 04:22:28
【问题描述】:

我正在将一个非常巨大的文件加载到 postgresql 数据库中。为此,我首先在文件中使用split 来获取较小的文件(每个30Gb),然后使用GNU Parallelpsql copy 将每个较小的文件加载到数据库中。

问题是拆分文件大约需要 7 个小时,然后它开始为每个内核加载一个文件。我需要一种方法来告诉split 每次完成写入文件时将文件名打印到std 输出,这样我就可以将它通过管道传输到Parallel 并在split 完成写入时开始加载文件.像这样的:

split -l 50000000 2011.psv carga/2011_ | parallel ./carga_postgres.sh {}

我已阅读 split 手册页,但找不到任何内容。有没有办法使用split 或任何其他工具来做到这一点?

【问题讨论】:

  • split --verbose 可能吗?
  • @KevinDTimm 详细选项在开始创建文件时打印,而不是在完成时打印
  • 因此,当它创建文件 X2 时,开始解析文件 X1 :)
  • @KevinDTimm 但我想避免需要额外的脚本来做到这一点。

标签: bash split gnu-parallel


【解决方案1】:

您可以让并行进行拆分:

<2011.psv parallel --pipe -N 50000000 ./carga_postgres.sh

请注意,手册页建议使用--block 而不是-N,这仍会在记录分隔符处拆分输入,默认情况下\n,例如:

<2011.psv parallel --pipe --block 250M ./carga_postgres.sh

测试--pipe-N

这是一个将 100 个数字的序列拆分为 5 个文件的测试:

seq 100 | parallel --pipe -N23 'cat > /tmp/parallel_test_{#}'

检查结果:

wc -l /tmp/parallel_test_[1-5]

输出:

 23 /tmp/parallel_test_1
 23 /tmp/parallel_test_2
 23 /tmp/parallel_test_3
 23 /tmp/parallel_test_4
  8 /tmp/parallel_test_5
100 total

【讨论】:

  • parallel 的--pipe -N 50000000 选项会将50000000 行发送到carga_postgres.sh stdin?
  • @Topo:是的,没错。我编辑了答案以说明 --pipe-N 的工作原理。
  • 由于您输入的内容很大,您可能需要查看 --joblog --resume --resume-failed(需要版本 20130222)。
  • @Thor 我真的很喜欢你的回答,但是当我运行它时,zsh 给了我一个错误,比如:zsh: 4 expected number,我只能找出问题所在。
  • @Topo:我也使用zsh,但无法重现此错误。测试示例是否有效?您使用的是什么版本的parallelzsh?如果您在zsh -f 下运行它会有所帮助吗?
【解决方案2】:

如果您使用GNU split,您可以使用--filter 选项来做到这一点

‘--filter=command’
使用此选项,不是简单地写入每个输出文件,而是通过管道写入每个输出文件的指定 shell 命令。命令应使用 $FILE 环境变量,该变量为每次调用命令设置为不同的输出文件名。

您可以创建一个shell脚本,该脚本创建一个文件并在后台启动carga_postgres.sh

#! /bin/sh

cat >$FILE
./carga_postgres.sh $FILE &

并使用该脚本作为过滤器

split -l 50000000 --filter=./filter.sh 2011.psv

【讨论】:

  • cat 在您的示例中所做的是,将split 通过标准输入发送的每一行写入文件$FILE,然后将$FILE 文件名传递给carga_postgres?
  • @Topo 正确,拆分将行发送到过滤器的标准输入。 $FILE 是 split 选择的名称。当然,您可以随意使用其他唯一名称。
  • 我一直在做一些小测试(只需在每个文件中执行 head -1)测试,当我在过滤器标志的末尾添加 &amp; 时,为 @987654333 生成的文件@ 是空的,并且命令head 没有t display anything... but if I execute the split` 没有&amp; 拆分生成的文件是正常的,head 打印到屏幕上......这是正确的行为还是我正在做一个糟糕的解释?
  • @Topo 我刚刚对此进行了测试,如果您使用&amp; 运行过滤器,标准输入确实是从/dev/null 重定向的。但是如果你不运行过滤器,split 将等到过滤器退出,然后再启动下一个过滤器。看来,您必须使用脚本版本才能并行运行 carga_postgres.sh。我相应地更新了我的答案。
猜你喜欢
  • 1970-01-01
  • 2013-09-08
  • 1970-01-01
  • 2023-03-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多