我建议您使用基于Python等跨平台解释型语言的解决方案。
进程启动器
首先,您需要定义一个类来管理要启动的命令进程。
class PFSProcess(object):
def __init__(self, submodule, path, cmd):
self.__submodule = submodule
self.__path = path
self.__cmd = cmd
self.__output = None
self.__p = None
def run(self):
self.__output = "\n\n" + self.__submodule + "\n"
self.__p = subprocess.Popen(self.__cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True,
cwd=os.path.join(self.__path, self.__submodule))
self.__output += self.__p.communicate()[0].decode('utf-8')
if self.__p.communicate()[1]:
self.__output += self.__p.communicate()[1].decode('utf-8')
print(self.__output)
多线程
下一步是实现多线程执行。Python中包含了一个非常强大的线程库,你可以通过导入以下包来使用它:
import threading
在创建线程之前,您需要创建一个工作器,即每个线程要调用的函数:
def worker(submodule_list, path, command):
for submodule in submodule_list:
PFSProcess(submodule, path, command).run()
如您所见,工作人员会收到一个子模块列表。为了清晰起见,并且因为它超出了我们的范围,我建议您查看 .gitmodules
,从那里您可以读取文件并生成子模块列表。
<提示>
作为基本指南,您可以在每个子模块中找到以下行:
path = relative_path/project
为此,您可以使用以下正则表达式:
用于此目的,您可以使用此正则表达式:
'path ?= ?([A-za-z0-9-_]+)(\/[A-za-z0-9-_]+)*([A-za-z0-9-_])'
如果正则表达式匹配成功,您可以在同一行中使用以下代码获取相对路径:
' ([A-za-z0-9-_]+)(\/[A-za-z0-9-_]+)*([A-za-z0-9-_])'
请注意,最后一个正则表达式返回相对路径并在第一个位置带有空格字符。
</提示>
然后将子模块列表分成尽可能多的块,以适应所需的作业数:
num_jobs = 8
i = 0
for submodule in submodules:
submodule_list[i % num_jobs].append(submodule)
i += 1
最后将每个数据块(任务)分发给每个线程,并等待所有线程完成:
for i in range(num_jobs):
t = threading.Thread(target=worker, args=(list_submodule_list[i], self.args.path, self.args.command,))
self.__threads.append(t)
t.start()
for i in range(num_jobs):
self.__threads[i].join()
显然,我已经介绍了基本概念,但您可以访问GitHub上的parallel_foreach_submodule(PFS)项目以获取完整实现。请参考
parallel_foreach_submodule (PFS)。