推荐的方式批准stdin行到另一个重复的命令,如xargs,但通过stdin而不是参数?

我有一个数据导入脚本,可以读取行并将它们添加到数据库,非常好。 不幸的是,脚本(或其运行时或数据库库或其他)中的某些内存泄漏,大量导入使用单调增加的主内存,导致交换缓慢,然后耗尽内存过程死亡。 将import分成多个运行是一个解决方法; 我一直在做split然后在每一块做一个循环的执行导入脚本。

但我宁愿跳过制作分割文件,这感觉应该是一个单线程。 实际上,似乎应该有一个相当于xargs的行,而不是作为parameter passing给stdin上的指定命令。 如果这个假设的命令是xlines ,那么我期望以下内容为myimport每批最多50,000行运行myimport脚本:

 cat giantfile.txt | xlines -L 50000 myimport 

我错过了一些其他名称下的xlines likefunction,或隐藏在其他命令的选项中? 或者可以在几行BASH脚本中完成xlines

使用GNU并行 – 在这里可用。

您将需要--pipe选项以及--block选项(这需要一个字节大小,而不是行数)。

有些东西是:

 cat giantfile.txt | parallel -j 8 --pipe --block 4000000 myimport 

(这是选择50,000行的块大小* 80字节= 4000000,这里也可以缩写为4m )。

如果您不希望作业实际上并行运行,请将8更改为1 。 或者,您可以将其完全保留,并且每个CPU核心将运行一个作业。

你也可以通过跑步来避开cat

 parallel ... < giantfile.txt 

将以下代码保存为test.sh脚本。

  #!/bin/bash tempFile=/tmp/yourtempfile.temp rm -f tempFile > /dev/null 2>&1 declare -i cnt=0 while read line do cnt=$(($cnt+1)) if [[ $cnt < $1 || $cnt == $1 ]]; then echo $line >> tempFile else echo $line >> tempFile cat tempFile | myimport rm -f tempFile > /dev/null 2>&1 cnt=$((0)) fi done < $2 exit 0 

然后运行./test.sh 500000 giantfile.txt 。 我使用tempFile来保存指定数量的行,然后使用您的导入脚本处理它。 我希望它有帮助。

我的方法,没有安装parallel ,也没有写入临时文件:

 #!/bin/bash [ ! -f "$1" ] && echo "missing file." && exit 1 command="$(which cat)" # just as example, insert your command here totalSize="$(wc -l $1 | cut -f 1 -d ' ')" chunkSize=3 # just for the demo, set to 50000 in your version offset=1 while [ $[ $totalSize + 1 ] -gt $offset ]; do tail -n +$offset $1 | head -n $chunkSize | $command let "offset = $offset + $chunkSize" echo "----" done 

测试:

 seq 1000 1010 > testfile.txt ./splitter.sh testfile.txt 

输出:

 1000 1001 1002 ---- 1003 1004 1005 ---- 1006 1007 1008 ---- 1009 1010 ---- 

这样,解决方案仍然是可移植的,性能比临时文件更好。