如何平行我的bash脚本使用`find`而不面临竞争条件?

如何平行我的bash脚本使用`find`而不面临竞争条件?,第1张

概述如何平行我的bash脚本使用`find`而不面临竞争条件? @H_301_0@我试图执行这样的命令:

@H_301_0@find ./ -name "*.gz" -print -exec ./extract.sh {} ;

@H_301_0@gz文件本身很小。 目前我的extract.sh包含以下内容:

@H_301_0@# Start delimiter echo "#####" $1 >> Info zcat $1 > temp # SerIEs of greps to extract some useful information grep -o -P "..." temp >> Info grep -o -P "..." temp >> Info rm temp echo "####" >> Info

@H_301_0@显然,这是不可并行的,因为如果我运行多个extract.sh实例,它们都会写入同一个文件。 什么是这样做的聪明方式?

@H_301_0@我有一个32位核心马力巨大的机器上的80K gz文件。

@H_301_0@单行打印“grep -o”输出

@H_301_0@如果使用位于PATH中的二进制文件的名称命名bash脚本函数,会发生什么情况?

@H_301_0@如何在bash for循环中使用variables

@H_301_0@有一个具有相同名称但文件不同的文件的文件夹

@H_301_0@bash关联数组键string冒号给出错误

@H_301_0@awk不打印分隔符

@H_301_0@如何根据目录名称更改多个文件的内容?

@H_301_0@当使用xargs(并行)时如何获得退出代码

@H_301_0@有什么区别:“。 “或”source “,”bash or $ SHELL “,”./ “或”“?

@H_301_0@使用脚本从pdf文档获取文本

@H_301_0@我会创建一个临时目录。 然后为每个grep创建一个输出文件(基于它处理的te文件的名称)。 在/tmp下创建的文件位于RAM磁盘上,因此不会因大量写入而使硬盘崩溃。

@H_301_0@然后你可以在最后把所有的东西都集中在一起,或者让每个grep在完成时发出另一个进程的信号,这个进程可以立即开始捕获文件(并在完成时删除它们)。

@H_301_0@例:

@H_301_0@working_dir="`pwd`" temp_dir="`mktemp -d`" cd "$temp_dir" find "$working_dir" -name "*.gz" | xargs -P 32 -n 1 extract.sh cat *.output > "$working_dir/Info" rm -rf "$temp_dir"

@[email protected]

@H_301_0@filename=$(basename $1) output="$filename.output" extracted="$filename.extracted" zcat "$1" > "$extracted" echo "#####" $filename > "$output" # SerIEs of greps to extract some useful information grep -o -P "..." "$extracted" >> "$output" grep -o -P "..." "$extracted" >> "$output" rm "$extracted" echo "####" >> "$output"

@H_301_0@假设(只是为了简单和清晰)所有的文件都以az开头。

@H_301_0@所以你可以同时使用26个内核,当为每个字母启动一个如上所示的查找序列时。 每个“查找”需要生成一个自己的聚合文件

@H_301_0@find ./ -name "a*.gz" -print -exec ./extract.sh a {} ; & find ./ -name "b*.gz" -print -exec ./extract.sh b {} ; & .. find ./ -name "z*.gz" -print -exec ./extract.sh z {} ;

@H_301_0@(提取需要采取第一个参数来分隔“信息”目标文件)

@H_301_0@当你想要一个大的聚合文件只是加入所有聚合。

@H_301_0@但是,我不相信用这种方法来取得成绩。 最后所有的文件内容都会被序列化。

@H_301_0@可能的硬盘磁头移动将会是unzip(cpu)性能的限制。

@H_301_0@但是,让我们试试

@H_301_0@通过findutils源代码的快速检查发现,find为每个exec启动一个子进程。 我相信它会继续下去,尽管我可能会误解来源。 正因为如此,你已经是平行的,因为 *** 作系统将处理你的核心共享。 通过虚拟内存的魔力,相同的可执行文件将大部分共享相同的内存空间。

@H_301_0@你将遇到的问题是文件锁定/数据混合。 随着每个小孩的运行,它会将信息输入到您的info文件中。 这些是个别的脚本命令,所以他们会像意大利面一起混合输出。 这并不能保证文件将是有序的! 只是所有的个人文件的内容将保持在一起。

@H_301_0@为了解决这个问题,你只需要利用shell创建一个临时文件(使用tempfile )的能力,将每个脚本转储到临时文件中,然后让每个脚本将临时文件捕获到info文件中。 使用后不要忘记删除临时文件。

@H_301_0@如果临时文件在内存中(请参阅tmpfs ),那么除了写入最终文件并运行查找搜索之外,您将避免被IO限制。

@H_301_0@Tmpfs是一个特殊的文件系统,使用你的内存作为“磁盘空间”。 它将占用你所允许的内存量,而不是使用超过它需要的内存量,如果内存满了,则根据需要交换到磁盘。

@H_301_0@使用:

@H_301_0@创建一个挂载点(我喜欢/ mnt / ramdisk或者/ media / ramdisk)

@H_301_0@以root身份编辑/ etc / fstab

@H_301_0@添加tmpfs /mnt/ramdrive tmpfs size=1G 0 0

@H_301_0@以root用户身份运行umount来安装新的ramdrive。 它也将安装在启动。

@H_301_0@有关所有可用选项,请参阅fstab上的wikipedia条目 。

@H_301_0@您可以使用xargs并行运行搜索。 --max-procs限制执行的进程数(默认值为1):

@H_301_0@find ./ -name "*.gz" -print | xargs --max-args 1 --max-procs 32 ./extract.sh

@H_301_0@在./extract.sh ,可以使用mktemp将每个.gz中的数据写入临时文件,所有这些文件稍后可以组合使用:

@H_301_0@# Start delimiter tmp=`mktemp -t Info.XXXXXX` src=$1 echo "#####" $1 >> $tmp zcat $1 > $tmp.unzip src=$tmp.unzip # SerIEs of greps to extract some useful information grep -o -P "..." $src >> $tmp grep -o -P "..." $src >> $tmp rm $src echo "####" >> $tmp

@H_301_0@如果你有大量的马力,你可以直接使用zgrep ,而不需要先解压。 但是如果以后有很多grep , zcat可能会更快。

@H_301_0@无论如何,稍后将所有内容组合成一个文件:

@H_301_0@cat /tmp/Info.* > Info rm /tmp/Info.*

@H_301_0@如果您关心的是.gz文件的顺序, ./extract.sh第二个参数应用于./extract.sh :

@H_301_0@find files/ -name "*.gz" | nl -n rz | sed -e 's/t/n/' | xargs --max-args 2 ...

@H_301_0@在./extract.sh :

@H_301_0@tmp=`mktemp -t Info.$1.XXXXXX` src=$2

@[email protected]中的多个grep调用可能是这里的主要瓶颈。 一个显而易见的优化是只读取一次文件,然后按照所需的顺序打印摘要。 作为一个额外的好处,我们可以推测报告可以写成一个单独的块,但它可能不会完全阻止交错输出。 不过,这是我的尝试。

@H_301_0@#!/bin/sh for f; do zcat "$f" | perl -ne ' /(pattern1)/ && push @pat1,$1; /(pattern2)/ && push @pat2,$1; # ... END { print "##### '"$1"'n"; print join ("n",@pat1),"n"; print join ("n",@pat2),"n"; # ... print "#### '"$f"'n"; }' done

@H_301_0@在awk而不是Perl中做这个可能会稍微有效些,但是因为你正在使用grep -P我认为保持相同的正则表达式语法是有用的。

@H_301_0@脚本接受多个.gz文件作为输入,因此您可以使用find -exec extract.sh {} +或xargs来启动大量的并行进程。 使用xargs您可以尝试在连续作业和并行作业之间找到平衡点,方法是在一个批处理中为每个新进程提供100到500个文件。 您可以节省新进程的数量,但会在并行中失败。 一些实验应该揭示平衡应该是什么,但是这只是我将我的帽子拉出一个数字,看看它是否已经足够好了。

@H_301_0@当然,如果你的输入文件足够小,那么多个grep调用将会耗尽磁盘缓存,并且比起启动Perl的开销要快。

总结

以上是内存溢出为你收集整理的如何平行我的bash脚本使用`find`而不面临竞争条件?全部内容,希望文章能够帮你解决如何平行我的bash脚本使用`find`而不面临竞争条件?所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1155035.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-01
下一篇 2022-06-01

发表评论

登录后才能评论

评论列表(0条)

保存