У меня есть репозиторий Git, который содержит набор файлов конфигурации и скриптов Python.
В репозитории сервера у меня есть ловушка после получения, которая:
Как это:
#!/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
Все это работает нормально, но клиент Git зависает, пока работает ловушка, и будет оставаться в таком состоянии, пока я не отменю вручную. Чтобы было ясно, ловушка на стороне сервера делает завершено успешно, но клиент прекращает регистрацию на полпути.
Я знаю, что могу исправить проблему зависания, переместив настройку и выполнение python в отдельный файл bash и используя nohup
или disown
так что он продолжит выполнение после закрытия терминала. Однако для этого потребуется, чтобы я регистрировал результат выполнения скрипта отдельно, а не отображал его в журнале git push.
Если я имитирую push, вызывая ловушку post-receive вручную, ловушка завершится успешно.
hooks/post-receive <<MARK
09998130e13827a097797ff2fd3a973e91665960 fcb0b23a62f47bb73d6ccf2e6bfce324a04eeace master
MARK
Я проверил дочерние процессы на предмет перехвата, чтобы убедиться, что что-то не выходит должным образом. Насколько я могу судить, все дочерние процессы полностью завершаются до продолжения родительского сценария.
я звонил ps auxf
после каждой команды в хуке post-receive, чтобы увидеть, как выглядит дерево процессов, и он всегда возвращал:
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
Гнездо большое, потому что я вошел в систему через ssh и sudo был root, а затем su'd пользователю git ... но важная часть находится в последних двух строках.
Я определил строку, которая вызывает зависание:
python3 -m virtualenv venv >> "setup.log"
Если я удалю эту строку из ловушки и настрою виртуальную среду вручную перед отправкой обновления, то отправка завершится успешно.
Я считаю что либо python source/some_script.py --param=value
или pip install
оставляет висящий дочерний процесс.
Судя по моим экспериментам, я полагаю, что у git есть логика на стороне сервера, которая ожидает, пока все дочерние процессы останутся post-receive
сценарий. Он вечно ждет повешенного ребенка.
Пожалуйста, подтвердите свой прогноз, что сценарий пост-получения всегда полностью завершается: запускать вручную post-receive
в оболочке, затем найдите детей с ps