git post-receive 挂钩不在后台 运行
git post-receive hook not running in background
根据 git documentation,post-receive 挂钩实质上会阻止回购,直到它完成:
... the client doesn’t disconnect until it has completed, so be careful if you try to do anything that may take a long time.
如果您需要钩子来启动一个构建作业,然后在启动另一个作业(比如部署)之前轮询它是否完成,这会导致问题。例如,当所述脚本为 运行.
时,构建服务器无法从存储库中获取
我们还假设您完全没有能力将脚本放在 git 服务器上作为 shell 命令执行,整个 nohup /usr/bin/env python /path/to/post_receive.py 2>&1 > /dev/null &
方法类似于 this question.
我们还假设您已经尝试了与 this 类似的整个双重 os.fork()
'ing 守护进程和一些其他问题(non-working 下面的示例代码),发现 git 在完成挂钩之前仍然等待 long-running child 完成。
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 挂钩实际在后台运行而不会阻塞回购协议?
编辑
工作 没有异常处理的最小结构...感谢@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()
您需要关闭所有描述符访问,以便 ssh 知道它永远不会再获得任何数据。换句话说,在描述符 0 到 2 上调用 os.close
。实际上你需要那些 open,所以最好打开 os.devnull
和 os.dup2
0、1 和 2 上的结果描述符(对于真正强大的软件,请确保 os.open
还没有 return 一个值 0 <= fd <= 2
,当然,如果是,那没关系,只需将其保持在原位,同时复制其余部分)。
(你仍然需要通常的双叉技巧,放弃会话 ID 等可能是明智的。在一些 Unix 派生的系统中,有一个库例程称为 daemon
,它可能在 libc 或 libutil 中,它会为你做这一切。一些细节不可避免地 OS 相关,例如放弃控制终端的方式(如果有的话)。但是,链接 [=23] 中缺少的主要内容=]-特定答案是 stdin/stdout/stderr 描述符的替换。)
根据 git documentation,post-receive 挂钩实质上会阻止回购,直到它完成:
... the client doesn’t disconnect until it has completed, so be careful if you try to do anything that may take a long time.
如果您需要钩子来启动一个构建作业,然后在启动另一个作业(比如部署)之前轮询它是否完成,这会导致问题。例如,当所述脚本为 运行.
时,构建服务器无法从存储库中获取我们还假设您完全没有能力将脚本放在 git 服务器上作为 shell 命令执行,整个 nohup /usr/bin/env python /path/to/post_receive.py 2>&1 > /dev/null &
方法类似于 this question.
我们还假设您已经尝试了与 this 类似的整个双重 os.fork()
'ing 守护进程和一些其他问题(non-working 下面的示例代码),发现 git 在完成挂钩之前仍然等待 long-running child 完成。
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 挂钩实际在后台运行而不会阻塞回购协议?
编辑
工作 没有异常处理的最小结构...感谢@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()
您需要关闭所有描述符访问,以便 ssh 知道它永远不会再获得任何数据。换句话说,在描述符 0 到 2 上调用 os.close
。实际上你需要那些 open,所以最好打开 os.devnull
和 os.dup2
0、1 和 2 上的结果描述符(对于真正强大的软件,请确保 os.open
还没有 return 一个值 0 <= fd <= 2
,当然,如果是,那没关系,只需将其保持在原位,同时复制其余部分)。
(你仍然需要通常的双叉技巧,放弃会话 ID 等可能是明智的。在一些 Unix 派生的系统中,有一个库例程称为 daemon
,它可能在 libc 或 libutil 中,它会为你做这一切。一些细节不可避免地 OS 相关,例如放弃控制终端的方式(如果有的话)。但是,链接 [=23] 中缺少的主要内容=]-特定答案是 stdin/stdout/stderr 描述符的替换。)