git post-receive hook没有在后台运行

时间:2017-01-05 20:32:21

标签: python linux git background-process

根据git documentation,post-receive hook基本上阻止了repo直到它完成:

  

...客户端在完成之前不会断开连接,因此如果您尝试执行可能需要很长时间的任何操作,请务必小心。

如果您需要挂钩启动构建作业,然后在启动另一个(例如部署)作业之前轮询它的完成,则会导致问题。例如,在所述脚本运行时,构建服务器无法从存储库中获取。

我们还假设你完全没有能力将你的脚本放在git服务器上作为shell命令执行,整个nohup /usr/bin/env python /path/to/post_receive.py 2>&1 > /dev/null &方法类似于this question

我们还假设您已尝试过与this类似的整个双os.fork()守护进程以及其他一些问题(非工作示例代码如下)并发现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()

1 个答案:

答案 0 :(得分:3)

您需要关闭所有描述符访问权限,以便ssh知道它永远不会再获取任何数据。换句话说,在描述符0到2上调用os.close。实际上,您需要 open ,因此最好打开os.devnull和{{ 1}}结果描述符超过0,1和2(对于真正健壮的软件,确保os.dup2不会返回值os.open,当然 - 如果是,那么&#39} ;好吧,只需将其保留在原位,然后重复其余部分。)

(你还需要通常的双叉技巧,抛弃会话ID等可能是明智的。在一些Unix派生系统中,有一个名为0 <= fd <= 2的库例程,可能在libc或libutil,它可以为你完成所有这些。一些细节不可避免地依赖于操作系统,例如放弃控制终端的方式。但是,你链接的Python特定答案中缺少的主要内容是替换stdin / stdout / stderr descriptors。)