使用bash和常用工具为Linux构建最小任务队列系统的最佳/最简单方法是什么?
我有一个9'000行的文件,每行有一个bash命令行,命令是完全独立的。
command 1 > Logs/1.log
command 2 > Logs/2.log
command 3 > Logs/3.log
...
我的盒子有多个核心,我想同时执行X任务。我在网上搜索了一个很好的方法来做到这一点。显然,很多人都有这个问题,但到目前为止还没有人有一个好的解决方案。
如果解决方案具有以下功能,那就太好了:
command; command
)ls > /tmp/ls.txt
)如果它可以在其他Unix克隆上运行而没有太多异乎寻常的要求,则可以获得奖励。
答案 0 :(得分:14)
您可以将命令列表转换为Makefile吗?如果是这样,你可以运行“make -j X”。
答案 1 :(得分:9)
GNU Parallel http://www.gnu.org/software/parallel/是一种比PPSS更加通用的并行工具。
如果runfile包含:
command 1 > Logs/1.log
command 2 > Logs/2.log
command 3 > Logs/3.log
你可以这样做:
cat runfile | parallel -j+0
将为每个CPU核心运行一个命令。
如果您的命令如上所述,您甚至不需要运行文件,但可以执行:
seq 1 3 | parallel -j+0 'command {} > Logs/{}.log'
如果有更多计算机可用于处理,您可能需要查看GNU Parallel的--sshlogin和--trc选项。
答案 2 :(得分:0)
好的,在这里发布问题后,我发现以下项目看起来很有希望:ppss。
编辑:不是我想要的,PPSS专注于处理“目录A中的所有文件”。
答案 3 :(得分:0)
嗯,无论如何,这是一个有趣的问题。
这就是我要做的,当然假设 bash(1)。
N=15
。trap signalHandler SIGCHLD
wait
s。现在,它运行第一个N
命令,然后等待。当第一个子节点终止时,等待返回,它读取另一行,运行新命令,然后再次等待。
现在,这是一个案例,负责许多工作紧密结束。我怀疑你可以使用更简单的版本:
N=15
COUNT=N
cat mycommands.sh |
while read cmd
do
eval $cmd &
if $((count-- == 0))
then
wait
fi
od
现在,这个命令将启动前15个命令,然后在某个命令终止时一次运行其余一个命令。
答案 4 :(得分:0)
答案 5 :(得分:0)
您可以使用 xargs 命令, - max-procs 可以执行您想要的操作。例如,查理·马丁解决方案变成了xargs:
tr '\012' '\000' <mycommands.sh |xargs --null --max-procs=$X bash -c
细节:
我使用此mycommands.sh文件测试了它,例如:
date
date "+%Y-%m-%d" >"The Date".txt
wc -c <'The Date'.txt >'The Count'.txt
答案 6 :(得分:0)
这是一个特例,但如果您正在尝试处理一组文件并生成另一组输出文件,则可以启动#cores进程数,并在处理之前检查输出文件是否存在。下面的示例将.m4b文件的目录转换为.mp3文件:
只需像拥有核心一样多次运行此命令:
ls * m4b | while read f;做测试-f $ {f%m4b} mp3 || mencoder -of rawaudio“$ f”-oac mp3lame -ovc copy -o $ {f%m4b} mp3;完成&amp;
答案 7 :(得分:0)
你可以看到我的任务队列写在bash上:https://github.com/pavelpat/yastq
答案 8 :(得分:0)
任务队列+并行化+动态添加
使用FIFO,此脚本自行分叉以处理队列。这样,您可以动态地向队列添加命令(当队列已经启动时)。
用法:./queue命令[子项数] [队列名称]
示例,1个线程:
./queue "sleep 5; echo ONE" ./queue "echo TWO"
输出:
ONE TWO
示例,有2个帖子:
./queue "sleep 5; echo ONE" 2 ./queue "echo TWO"
输出:
TWO ONE
示例,有2个队列:
./queue "sleep 5; echo ONE queue1" 1 queue1 ./queue "sleep 3; echo ONE queue2" 1 queue2
输出:
ONE queue2 ONE queue1
脚本(将其保存为“queue”和chmod + x队列):
#!/bin/bash #Print usage [[ $# -eq 0 ]] && echo Usage: $0 Command [# of children] [Queue name] && exit #Param 1 - Command to execute COMMAND="$1" #Param 2 - Number of childs in parallel MAXCHILD=1 [[ $# -gt 1 ]] && MAXCHILD="$2" #Param 3 - File to be used as FIFO FIFO="/tmp/defaultqueue" [[ $# -gt 2 ]] && FIFO="$3" #Number of seconds to keep the runner active when unused TIMEOUT=5 runner(){ #Associate file descriptor 3 to the FIFO exec 3"$FIFO" while read -u 3 -t $TIMEOUT line; do #max child check while [ `jobs | grep Running | wc -l` -ge "$MAXCHILD" ]; do sleep 1 done #exec in backgroud (eval "$line")& done rm $FIFO } writer(){ #fork if the runner is not running lsof $FIFO >/dev/null || ($0 "QueueRunner" "$MAXCHILD" "$FIFO" &) #send the command to the runner echo "$COMMAND" > $FIFO } #Create the FIFO file [[ -e "$FIFO" ]] || mkfifo "$FIFO" #Start the runner if in the runner fork, else put the command in the queue [[ "$COMMAND" == "QueueRunner" ]] && runner || writer