Как предотвратить зависание клиента 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.
- Что вызывает зависание клиента git?
- Как я могу отслеживать состояние выполнения скриптов в 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