How to run long-running post-receive hook script in the background on Bitbucket Server and Data Center
Platform notice: Server and Data Center only. This article only applies to Atlassian products on the Server and Data Center platforms.
Support for Server* products ended on February 15th 2024. If you are running a Server product, you can visit the Atlassian Server end of support announcement to review your migration options.
*Except Fisheye and Crucible
The content on this page relates to platforms which are not supported. Consequently, Atlassian Support cannot guarantee providing any support for it. Please be aware that this material is provided for your information only and using it is done so at your own risk.
Summary
This article explains how to run long-running post-receive hook script in the background on Bitbucket Server and Data Center installations.
If Bitbucket is configured to use a post-receive hook script that is calling a long-running program, this program will block the hook script, and Bitbucket will log the alert message "Slow hook script detected" to atlassian-bitbucket-alerts.log
.
To ensure that Bitbucket will not wait for this long-running program to finish, it must be run as a daemon in the background.
Environment
8.11, but also applicable to other versions.
Solution
Calling another script from the main hook script with added "&" does not work. Bitbucket still waits for all process' children to complete before considering hook execution completed.
What should be done here is to daemonize the long-running program. This can be done directly inside that program's code, but we can also do this using a small shell wrapper; the idea for this one-liner comes from https://stackoverflow.com/a/49183740:
( cd /; umask 0; setsid ${SCRIPT} </dev/null &>/dev/null & ) &
SCRIPT
here points to the program we want to daemonize.- It is possible to pass parameters to
SCRIPT.
The most important points that we are doing here are:
- We make a subshell using parenthesis and start that subshell in the background.
- By "setsid" we make a new process-group session.
- We close new script's STDIN, STDOUT, STDERR.
- Changing the working directory to "/" and setting umask are not important in this case; they are included here because both are considered part of good practice when daemonizing processes.