Назад | Перейти на главную страницу

Как предотвратить зависание клиента Git во время перехвата пост-получения

У меня есть репозиторий 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.

  1. Что вызывает зависание клиента git?
  2. Как я могу отслеживать статус выполнения скрипта в клиенте git, не вызывая зависания клиента?

Звонок напрямую

Если я имитирую 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