I have a Git repository that contains a collection of config files and python scripts.
On the server repository, I have a post-receive hook that will:
- checkout the master branch,
- setup a python virtualenv,
- install the pip requirements,
- and run some scripts
#!/bin/bash while read oldrev newrev ref; do branch=$(git rev-parse --symbolic --abbrev-ref $ref) if [[ $branch == "master" ]]; then echo "Ref $ref received in branch $branch" echo "setup..." cd /srv/repo.git git --work-tree=/opt/work-dir checkout master -f cd /opt/work-dir echo "install virtual environment..." > "setup.log" python3 -m virtualenv venv >> "setup.log" echo "activate virtual environment..." >> "setup.log" source venv/bin/activate >> "setup.log" echo "install requirements..." >> "setup.log" pip install -r requirements.txt >> "setup.log" echo "done." >> "setup.log" echo "run scripts..." python source/some_script.py --param=value else echo "Ref $ref received, in branch $branch" echo "no action needed." fi done
All of this works fine, but the Git client hangs while the hook is running and will remain like that until I manually cancel. To be clear, the server-side hook does complete successfully, but the client stops logging part way through.
I am aware that I can fix the hanging issue by moving the python setup and execution to a separate bash file and using
disown so that it will continue executing once the terminal closes. However, this would require that I log the result of the script execution separately rather than having it display in the git push log.
- What is causing the git client to hang?
- How can I monitor the status of the script executions in the git client, without it causing the client to hang?
If I simulate a push by calling the post-receive hook manually, the hook will complete successfully.
hooks/post-receive <<MARK 09998130e13827a097797ff2fd3a973e91665960 fcb0b23a62f47bb73d6ccf2e6bfce324a04eeace master MARK
I have inspected the child-processes for the hook to see if something isn't exiting properly. As far as I can tell, all child processes exit fully before the parent script continues.
ps auxf after every command in the post-receive hook to see what the process tree looked like, and it always returned:
root 711 0.0 0.3 95184 6812 ? Ss Feb16 0:00 sshd: username [priv] username 720 0.0 0.2 95184 4660 ? S Feb16 0:04 \_ sshd: username @pts/1,pts/0,pts/2 username 725 0.0 0.1 19892 3712 pts/0 Ss Feb16 0:00 \_ -bash root 842 0.0 0.1 49484 3676 pts/0 S 02:49 0:00 | \_ sudo -i root 843 0.0 0.1 19940 3768 pts/0 S 02:49 0:00 | \_ -bash root 4616 0.0 0.1 50892 3428 pts/0 S 13:59 0:00 | \_ su - git git 4617 0.0 0.1 19920 3752 pts/0 S 13:59 0:00 | \_ -su git 5108 0.0 0.1 11256 3016 pts/0 S+ 17:26 0:00 | \_ /bin/bash hooks/post-receive git 5130 0.0 0.1 38456 3328 pts/0 R+ 17:27 0:00 | \_ ps auxf
The nest is large because I am logged in over ssh, and sudo'd to root, and then su'd to the git user... but the important part is in the last two lines.
Process of Elimination
I have identified the line that causes the hang:
python3 -m virtualenv venv >> "setup.log"
If I remove this line from the hook, and setup the virtual environment manually before pushing the update, then the push will complete successfully.