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

У меня есть Git-репозиторий, который содержит коллекцию файлов конфигурации и скриптов Python.

В репозитории сервера у меня есть хук пост-получения, который будет:

  • оформить заказ мастер ветки,
  • настроить питона virtualenv,
  • установить требования к пунктам,
  • и запустить несколько скриптов

Как это:

#!/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 log.

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

Звонить напрямую

Если я имитирую пуш, вызывая ловушку после получения вручную, ловушка завершится успешно.

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'd для root, а затем su'd для пользователя git... но важная часть находится в последних двух строках.

Процесс ликвидации

Я определил строку, которая вызывает зависание:

python3 -m virtualenv venv >> "setup.log"

Если я удаляю эту строку из ловушки и вручную настраиваю виртуальную среду перед отправкой обновления, то загрузка будет успешно завершена.

1 ответ

Я считаю, что либо python source/some_script.py --param=value или же pip install оставляет висячий дочерний процесс.

Из моих экспериментов, я думаю, у git есть некоторая логика на стороне сервера для ожидания всех дочерних процессов, оставленных post-receive скрипт. Он ждет нависшего ребенка навсегда.

Пожалуйста, подтвердите свой прогноз, что сценарий после получения всегда полностью завершается: запустить вручную post-receive в скорлупе, затем посмотрите на детей с ps

Другие вопросы по тегам