Python中文
首页
教程
问答
标签
搜索
登录
注册
并行文件匹配,Python
回答此问题可获得
20
贡献值,回答如果被采纳可获得
50
分。
<p>我正在尝试改进一个脚本扫描文件恶意代码。我们在一个文件中有一个regex模式的列表,每行一个模式。这些regex用于grep,因为我们当前的实现基本上是bash脚本find\grep组合框。bash脚本在我的基准目录上花费了358秒。我能够在72秒内编写一个python脚本,但还想改进更多。首先,我将发布基本代码,然后我尝试了一些调整:</p> <pre><code>import os, sys, Queue, threading, re fileList = [] rootDir = sys.argv[1] class Recurser(threading.Thread): def __init__(self, queue, dir): self.queue = queue self.dir = dir threading.Thread.__init__(self) def run(self): self.addToQueue(self.dir) ## HELPER FUNCTION FOR INTERNAL USE ONLY def addToQueue(self, rootDir): for root, subFolders, files in os.walk(rootDir): for file in files: self.queue.put(os.path.join(root,file)) self.queue.put(-1) self.queue.put(-1) self.queue.put(-1) self.queue.put(-1) self.queue.put(-1) self.queue.put(-1) self.queue.put(-1) self.queue.put(-1) self.queue.put(-1) self.queue.put(-1) self.queue.put(-1) self.queue.put(-1) self.queue.put(-1) self.queue.put(-1) self.queue.put(-1) self.queue.put(-1) self.queue.put(-1) self.queue.put(-1) self.queue.put(-1) self.queue.put(-1) class Scanner(threading.Thread): def __init__(self, queue, patterns): self.queue = queue self.patterns = patterns threading.Thread.__init__(self) def run(self): nextFile = self.queue.get() while nextFile is not -1: #print "Trying " + nextFile self.scanFile(nextFile) nextFile = self.queue.get() #HELPER FUNCTION FOR INTERNAL UES ONLY def scanFile(self, file): fp = open(file) contents = fp.read() i=0 #for patt in self.patterns: if self.patterns.search(contents): print "Match " + str(i) + " found in " + file ############MAIN MAIN MAIN MAIN################## ############MAIN MAIN MAIN MAIN################## ############MAIN MAIN MAIN MAIN################## ############MAIN MAIN MAIN MAIN################## ############MAIN MAIN MAIN MAIN################## ############MAIN MAIN MAIN MAIN################## ############MAIN MAIN MAIN MAIN################## ############MAIN MAIN MAIN MAIN################## ############MAIN MAIN MAIN MAIN################## fileQueue = Queue.Queue() #Get the shell scanner patterns patterns = [] fPatt = open('/root/patterns') giantRE = '(' for line in fPatt: #patterns.<a href="https://www.cnpython.com/list/append" class="inner-link">append</a>(re.compile(line.rstrip(), re.IGNORECASE)) giantRE = giantRE + line.rstrip() + '|' giantRE = giantRE[:-1] + ')' giantRE = re.compile(giantRE, re.IGNORECASE) #start recursing the directories recurser = Recurser(fileQueue,rootDir) recurser.start() print "starting scanner" #start checking the files for scanner in xrange(0,8): scanner = Scanner(fileQueue, giantRE) scanner.start() </code></pre> <p>这显然是调试\难看的代码,千万别介意队列.put(-1),我稍后会清理这个。有些压痕没有正确显示,尤其是在scanFile中。在</p> <p>不管怎样,我注意到了一些事情。使用1,4,甚至8个线程(对于X范围内的扫描仪(0,???))没什么区别。不管怎样,我还有72秒的时间。我想这是由于python的GIL。在</p> <p>与生成一个巨大的regex相反,我尝试将每一行(模式)作为compilex RE放在一个列表中,并在scanfile函数中遍历这个列表。这导致执行时间更长。在</p> <p>为了避免python的GIL,我尝试让每个线程fork都指向grep,如下所示:</p> ^{pr2}$ <p>这导致执行时间更长。在</p> <p>对提高绩效有什么建议吗。在</p> <p>::::::::::编辑::::::::</p> <p>我还不能回答我自己的问题,但是这里有几个问题的答案:</p> <p>@David Nehme-只是想让人们知道我有一百万队列.put(-1)的</p> <p>@Blender-标记队列的底部。我的扫描器线程一直在下降,直到到达底部的-1(而nextFile不是-1:)。处理器核心是8,但是由于GIL使用1个线程,4个线程,或8个线程没有区别。生成8个子进程导致代码明显变慢(142秒vs 72秒)</p> <p>@ed-是的,而且它和find\grep组合框一样慢,实际上更慢,因为它不分青红皂白地greps不需要的文件</p> <p>@Ron-不能升级,这一定是万能的。你认为这会加快72秒吗?贝什·格雷珀做了358秒。我的python giant RE方法使用1-8个线程执行72秒。popen方法w\8 thrads(8个子进程)运行时间为142秒。到目前为止,这个只重python的方法是一个明显的赢家</p> <p>@插管</p> <p>这是我们当前find\grep组合的主要部分(不是我的脚本)。很简单。还有一些其他的东西,比如ls,但是没有什么会导致5倍的减速。即使grep-r的效率稍微高一点,5倍的增长速度也是一个巨大的放缓。在</p> <pre><code> find "${TARGET}" -type f -size "${SZLIMIT}" -exec grep -Eaq --file="${HOME}/patterns" "{}" \; -and -ls | tee -a "${HOME}/found.txt" </code></pre> <p>python代码更高效,我不知道为什么,但我通过实验测试了它。我更喜欢用python来做这个。我已经用python实现了5倍的加速,我想让它更快一些。在</p> <p>:::::::::::优胜劣汰:::::::::::::::::</p> <p>看来我们赢了。在</p> <p>Intuied的shell脚本以34秒排在第二位,而@steveha的则以24秒排在第一位。由于我们很多盒子里没有Python2.6,我不得不把它冷冻起来。我可以编写一个shell脚本包装器来wget a tar并解包它。不过,为了简单起见,我确实喜欢Intuid。在</p> <p>谢谢你们所有的帮助,我现在有了一个高效的系统管理工具</p>
0 条评论
分类:
Python问答
请先
登录
后评论
默认排序
时间排序
1 个回答
匿名
1天前
擅长:python、mysql、java
<p>如果您愿意升级到3.2版或更高版本,可以利用concurrent.futures.ProcessPoolExecutor. 我认为它将比您尝试的popen方法提高性能,因为它将预先创建一个进程池,其中popen方法每次都会创建一个新进程。如果由于某种原因不能迁移到3.2版本,您可以编写自己的代码来为早期版本执行相同的操作。在</p>
请先
登录
后评论
针对此问题:
更多的回答
关注
89
关注
收藏
1
收藏,
216
浏览
网友 提问于 2天前
相关Python问题
我想从用户inpu创建一个类的实例
5 回答
我想从用户导入值,为此
10 回答
我想从用户那里得到一个整数输入,然后让for循环遍历该数字,然后调用一个函数多次
6 回答
我想从用户那里收到一个列表,并在其中执行一些步骤,然后在步骤完成后将其打印回来,但它没有按照我想要的方式工作
9 回答
我想从用户那里获取输入,并将值传递给(average=dict[x]/6),然后在那里获取resu
9 回答
我想从第一个列表中展示第一个词,然后从第二个列表中展示十个词,以此类推- Python
8 回答
我想从第一个空lin开始解析文本文件
2 回答
我想从简历、简历中提取特定部分
7 回答
我想从给定字典(python)的字符串中删除\u00a9、\u201d和类似的字符。
3 回答
我想从给定的网站Lin下载许多文件扩展名相同的Wget或Python文件
9 回答
我想从网上搜集一些关于抵押贷款的数据
6 回答
我想从网站上删除电子邮件地址
8 回答
我想从网站上读取数据该网站包含可下载的文件,然后我想用python脚本把它发送给oracle如何?
2 回答
我想从网站中提取数据,然后将其显示在我的网页上
2 回答
我想从网页上提取统计数据。
2 回答
我想从网页上解析首都城市,并在用户输入国家时在终端上打印它们
1 回答
我想从色彩图中删除前n个颜色,而不丢失原始颜色数
3 回答
我想从课堂上打印字典里的键
5 回答
我想从费用表中获取学生上次支付的费用,其中学生id=id
10 回答
我想从较低的顺序对多重列表进行排序,但我无法在一行中生成结果
2 回答