Bash 使用GNU与Split并行
我正在将一个相当大的文件加载到postgresql数据库中。为此,我首先在文件中使用Bash 使用GNU与Split并行,bash,split,gnu-parallel,Bash,Split,Gnu Parallel,我正在将一个相当大的文件加载到postgresql数据库中。为此,我首先在文件中使用split来获得较小的文件(每个30Gb),然后使用GNU Parallel和psql copy将每个较小的文件加载到数据库中 问题是分割文件大约需要7个小时,然后开始为每个核心加载一个文件。我需要的是一种方法,告诉split在每次完成文件写入时将文件名打印到std输出,这样我就可以通过管道将其传输到Parallel,并在split完成写入时开始加载文件。大概是这样的: split -l 50000000 201
split
来获得较小的文件(每个30Gb),然后使用GNU Parallel
和psql copy
将每个较小的文件加载到数据库中
问题是分割文件大约需要7个小时,然后开始为每个核心加载一个文件。我需要的是一种方法,告诉split
在每次完成文件写入时将文件名打印到std输出,这样我就可以通过管道将其传输到Parallel
,并在split
完成写入时开始加载文件。大概是这样的:
split -l 50000000 2011.psv carga/2011_ | parallel ./carga_postgres.sh {}
我已经阅读了
split
手册页,没有找到任何内容。有没有办法使用拆分
或任何其他工具执行此操作?您可以让parallel执行拆分:
<2011.psv parallel --pipe -N 50000000 ./carga_postgres.sh
测试--管道和-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
如果使用,可以使用--filter
选项执行此操作
'--filter=命令'
使用此选项,而不是简单地写入每个输出文件,而是通过管道写入每个输出文件的指定shell命令。命令应使用$FILE环境变量,该变量为每次调用命令时设置为不同的输出文件名
您可以创建一个shell脚本,该脚本创建一个文件并在后台的末尾启动carga_postgres.sh
#! /bin/sh
cat >$FILE
./carga_postgres.sh $FILE &
并使用该脚本作为过滤器
split -l 50000000 --filter=./filter.sh 2011.psv
split--verbose maybe?@KevinDTimm verbose选项在开始创建文件时打印,而不是在完成时打印,因此,在创建文件X2时,开始解析文件X1:)@KevinDTimm,但我想避免需要额外的脚本来执行此操作。parallel的--pipe-N 50000000
选项将50000000行发送到carga_postgres.sh
stdin?@Topo:是的。我对答案进行了编辑,以说明--pipe
和-N
的工作原理。由于您的输入量巨大,您可能需要查看--joblog--resume--resume failed(需要版本20130222)。@Thor我非常喜欢您的答案,但当我运行它时,zsh给了我一个错误,类似于:zsh:4预期的数字
,我只能找出问题所在。@Topo:我也使用了zsh
,但无法重现此错误。这个测试示例有效吗?您使用的是什么版本的parallel
和zsh
?如果您在zsh-f
下运行此程序是否有帮助?在您的示例中,cat
所做的是将split
通过stdin发送的每一行写入文件$file
,然后将$file
文件名传递给carga_postgres?@Topo Correct,split将这些行发送到过滤器的stdin$FILE
是split选择的名称。当然,您可以自由使用另一个唯一的名称。我已经做了一些小测试(只需在每个文件中执行head-1
),当我将和添加到过滤器标志的末尾时,为拆分生成的文件是空的,head
命令不显示任何内容。。。但是如果我在没有和的情况下执行
split`split,则分割生成的文件是正常的,head
会打印到屏幕上。。。这是正确的行为还是我做了一个糟糕的解释?@Topo我刚刚测试了这一点,如果您使用&
运行筛选器,则stdin确实从/dev/null
重定向。但是,如果在不使用的情况下运行筛选器,则split将等待筛选器退出,然后再启动下一个筛选器。因此,似乎必须使用脚本版本才能并行运行carga_postgres.sh。我相应地更新了我的答案。
split -l 50000000 --filter=./filter.sh 2011.psv