在Linux上从命令队列进行并行处理(bash、python、ruby等等)
我有一个包含200条命令的列表/队列,需要在Linux服务器上的shell中运行这些命令 我只希望一次最多从队列运行10个进程。有些过程需要几秒钟才能完成,而其他过程则需要更长的时间 当一个进程完成时,我希望下一个命令从队列中弹出并执行 有人有解决这个问题的代码吗 进一步阐述: 在某种队列中,有200件工作需要完成。我想一次最多完成10件工作。当线程完成一项工作时,它应该向队列询问下一项工作。如果队列中没有更多的工作,则线程应该死亡。当所有的线程都死掉了,这意味着所有的工作都完成了在Linux上从命令队列进行并行处理(bash、python、ruby等等),python,ruby,bash,shell,parallel-processing,Python,Ruby,Bash,Shell,Parallel Processing,我有一个包含200条命令的列表/队列,需要在Linux服务器上的shell中运行这些命令 我只希望一次最多从队列运行10个进程。有些过程需要几秒钟才能完成,而其他过程则需要更长的时间 当一个进程完成时,我希望下一个命令从队列中弹出并执行 有人有解决这个问题的代码吗 进一步阐述: 在某种队列中,有200件工作需要完成。我想一次最多完成10件工作。当线程完成一项工作时,它应该向队列询问下一项工作。如果队列中没有更多的工作,则线程应该死亡。当所有的线程都死掉了,这意味着所有的工作都完成了 我试图解决的
我试图解决的实际问题是使用imapsync将200个邮箱从旧邮件服务器同步到新邮件服务器。一些用户的邮箱很大,需要很长时间才能同步,而另一些用户的邮箱很小,同步速度很快。如果您打算使用Python,我建议您为此使用
具体地说 你能详细解释一下你所说的平行是什么意思吗?听起来您需要在队列中实现某种类型的锁定,这样您的条目就不会被选中两次,等等,而命令只运行一次 大多数排队系统都会作弊——他们只是写一个巨大的待办事项列表,然后选择十个项目,对它们进行操作,然后选择接下来的十个项目。没有并行化
如果您提供更多详细信息,我相信我们可以帮助您。GNU make和其他实现可能也有-j参数,该参数控制它将同时运行多少个作业。当一项工作完成后,make将开始另一项工作。好吧,如果它们在很大程度上相互独立,我会从以下方面考虑:
Initialize an array of jobs pending (queue, ...) - 200 entries
Initialize an array of jobs running - empty
while (jobs still pending and queue of jobs running still has space)
take a job off the pending queue
launch it in background
if (queue of jobs running is full)
wait for a job to finish
remove from jobs running queue
while (queue of jobs is not empty)
wait for job to finish
remove from jobs running queue
请注意,主循环中的尾部测试意味着当while循环迭代时,如果“jobs running queue”有空间,则可以防止循环过早终止。我认为逻辑是正确的
我可以很容易地在C语言中看到如何做到这一点-在Perl中也不会那么难,因此在其他脚本语言中也不会太难-Python、Ruby、Tcl等。我根本不确定我是否想在shell中完成它-shell中的wait命令等待所有子脚本终止,xargs可以用于对并行命令处理进行排队,而不是让某些子进程终止。在shell上。例如,始终并行进行3次睡眠,每次睡眠1秒,总共执行10次睡眠
echo {1..10} | xargs -d ' ' -n1 -P3 sh -c 'sleep 1s' _
它总共会睡4秒钟。如果您有一个名称列表,并且希望将名称传递给已执行的命令,再次并行执行3个命令,请执行以下操作:
cat names | xargs -n1 -P3 process_name
将执行命令process\u name alice、process\u name bob等等。我想您可以使用make和make-j xx命令来执行此操作 也许像这样的makefile
all : usera userb userc....
usera:
imapsync usera
userb:
imapsync userb
....
在python中,make-j 10-f makefile,您可以尝试:
import Queue, os, threading
# synchronised queue
queue = Queue.Queue(0) # 0 means no maximum size
# do stuff to initialise queue with strings
# representing os commands
queue.put('sleep 10')
queue.put('echo Sleeping..')
# etc
# or use python to generate commands, e.g.
# for username in ['joe', 'bob', 'fred']:
# queue.put('imapsync %s' % username)
def go():
while True:
try:
# False here means no blocking: raise exception if queue empty
command = queue.get(False)
# Run command. python also has subprocess module which is more
# featureful but I am not very familiar with it.
# os.system is easy :-)
os.system(command)
except Queue.Empty:
return
for i in range(10): # change this to run more/fewer threads
threading.Thread(target=go).start()
未经测试的
当然,python本身是单线程的。不过,在等待IO方面,您仍然可以从多线程中获益。Python似乎很适合您的问题。这是一个支持进程线程的高级包。对于这种作业,PPSS编写了:并行处理shell脚本。用谷歌搜索这个名字,你会找到的,我不会链接垃圾邮件。就是为了这个目的而做的
cat userlist | parallel imapsync
与其他解决方案相比,该解决方案的优点之一是它确保了输出不会混合。在工作中执行跟踪路由很好,例如:
(echo foss.org.my; echo www.debian.org; echo www.freenetproject.org) | parallel traceroute
gnu并行
pssh可能会有所帮助。zsh中的简单函数使用/tmp中的锁文件,在不超过4个子shell中并行化作业 唯一重要的部分是第一次测试中的glob标志: q:在测试中启用文件名全局绑定 [4] :仅返回第四个结果 N:忽略空结果上的错误 将其转换为posix应该很容易,不过会有点冗长 不要忘记用\来转义作业中的任何引号
这正是我所希望的。我编写了一些代码来生成Makefile。结果超过了1000行。谢谢我发现,如果任何命令退出时带有错误代码,make将退出,从而阻止将来作业的执行。在某些情况下,此解决方案并不理想。对此方案有何建议?@redmoskito如果您使用-k选项运行make,即使出现错误,它也会继续运行。如果您开始认为make不是任务调度器,而是并行编译工具。。我想更大的情况是“make-j”尊重依赖性,这使得这个解决方案一旦被普遍应用,就会令人振奋。1 os.system可以被新的改进的子流程模块所取代。2 CPython是否有GIL并不重要,因为您运行的是外部命令,而不是Python代码funct
如果将threading.Thread替换为multiprocessing.Process,将Queue替换为multiprocessing.Queue,那么代码将使用多个进程运行。pssh是用python编写的,我认为这看起来很理想。下次遇到类似问题时,我会检查一下。谢谢你用你的推荐更新这个帖子。太棒了!我们可以设置动态线程,例如80%的CPU/Ram允许吗?几乎正是我想要的/我又开始努力工作了,伙计,我喜欢这个工具。我知道它已经有3个小时了,我会一直使用它,直到地球上的石头都喊着让我停下来。Fedora 16将该工具包含在package Repository哇,我一直在使用xargs,从没想过它会有这个选项!对于您给出的第二个示例,如何修改该命令,使process_name可以接受多个参数?我想这样做:cat commands.txt | xargs-n1-P3 eval,commands.txt中有一组命令,每行一个,每个命令都有多个参数。问题是eval不起作用,因为它是一个内置的shellcommand@Eddy尝试使用shell作为要运行的程序;这允许您使用任意shell命令作为输入。上面的第一个答案是用sh实现的,但是也可以用bash实现。例如,如果commands.txt中有一堆看起来像echo test1的行;sleep1,您可以通过cat commands.txt | xargs-d'\n'-P3-n1/bin/bash-cyou等方式使用它,您也可以对特定的子进程使用wait命令。它可以被赋予任意数量的参数,每个参数都可以是pid或作业id。@BrianMinton:你可以用wait列出特定的pid,这是对的,但是你仍然会得到“所有pid都死了”的行为,而不是“第一个死了”的行为,这正是代码真正需要的。
#!/bin/zsh
setopt extendedglob
para() {
lock=/tmp/para_$$_$((paracnt++))
# sleep as long as the 4th lock file exists
until [[ -z /tmp/para_$$_*(#q[4]N) ]] { sleep 0.1 }
# Launch the job in a subshell
( touch $lock ; eval $* ; rm $lock ) &
# Wait for subshell start and lock creation
until [[ -f $lock ]] { sleep 0.001 }
}
para "print A0; sleep 1; print Z0"
para "print A1; sleep 2; print Z1"
para "print A2; sleep 3; print Z2"
para "print A3; sleep 4; print Z3"
para "print A4; sleep 3; print Z4"
para "print A5; sleep 2; print Z5"
# wait for all subshells to terminate
wait