【发布时间】:2017-01-05 20:32:20
【问题描述】:
根据git documentation,post-receive 钩子实际上会阻塞 repo,直到它完成:
...客户端在完成之前不会断开连接,因此如果您尝试执行任何可能需要很长时间的操作,请小心。
如果您需要钩子来启动构建作业,然后在启动另一个(例如部署)作业之前轮询它的完成,这会导致问题。例如,当所述脚本运行时,构建服务器无法从 repo 中获取。
我们还假设您完全没有能力将您的脚本放在 git 服务器上,以使用类似于 this question 的整个 nohup /usr/bin/env python /path/to/post_receive.py 2>&1 > /dev/null & 方法作为 shell 命令执行。
我们还假设您已经尝试了类似于this 的整个双重os.fork()'ing 守护进程和一些其他问题(non-working 示例代码如下)并发现 git 仍然在完成钩子之前等待长时间运行的孩子完成。
pid = os.fork()
if pid == 0:
os.setsid()
pid = os.fork()
if pid == 0:
long_running_post_receive_function()
else:
os._exit(0)
else:
for fd in range(0, 3):
os.close(fd)
os._exit(0)
那么,在这些限制条件下,有没有人成功地使用了一个长时间运行的 python post-receive 钩子,该钩子实际上在后台运行而不会阻塞 repo?
编辑
工作最小的结构,没有异常处理......感谢@torek和@jthill
pid = os.fork()
if pid == 0:
os.setsid()
pid = os.fork()
if pid == 0:
for fd in range(0, 3):
os.close(fd)
long_running_post_receive_function()
else:
os._exit(0)
else:
sys.exit()
【问题讨论】:
-
您还可以使用某种生产者/消费者模型,其中 post-receive 挂钩发送某种“异步消息”(可能就像触摸文件一样简单),这会导致消费者守护进程注意这一点并做好它的工作。
-
我当然同意这是一个替代方案,它确实违背了我想要完成的目标
-
我很累,但在我看来,您的 dup2() 操作在错误的地方。 fd 在长时间运行的过程中仍处于打开状态。
-
@jthill 就是这样!谢谢!
标签: python linux git background-process