【问题标题】:Why is this GitLab post-receive script terminated or stuck in a while loop?为什么这个 GitLab 接收后脚本会终止或卡在 while 循环中?
【发布时间】:2021-10-16 22:53:02
【问题描述】:

在编写了 post-receive 脚本以查找由 GitLab Runner CI 创建的最新 job.log 文件后,我注意到 post-receive 脚本在找到最新的 job.log 之前被终止或卡住了文件。特别是它不会超出 while 循环。此外,GitLab Runner 会给出 4:Deadline Exceeded 错误。

MWE

MWE 进行完整的部署,并将存储库上传到 GitLab 服务器并在存储库上运行 CI。但是,它还没有很好地推广,因此它(至少)具有以下要求:系统:Ubuntu 20.04,架构:AMD64。

git clone git@github.com:Deployment-Oneliners/Self-host-GitLab-Server-and-Runner-CI.git
cd Self-host-GitLab-Server-and-Runner-CI
git checkout post-receive
rm -r test/libs/*
chmod +x install-bats-libs.sh
./install-bats-libs.sh
./install_gitlab.sh -s -r
./test.sh

然后可以使用以下命令检查 GitLab docker 中 post-receive 脚本的日志:

sudo docker ps -a
sudo docker exec -t -i ab15330e020f  /bin/bash
cd /var/opt/gitlab/git-data/repositories/@hashed/d4/73/d4735e3a265e16eee03f59718b9b5d03019c07d8b6c51f90da3a666eec13ab35.git/refs/keep-around/9514d16aafc1d741ba6a9ff47718d632fa8d435b
cat post_receive_log.txt

要完全卸载 MWE,可以运行:./uninstall_gitlab.sh -y -h -r

相关代码

为了确定代码停止的位置,我让post-receive 脚本将大量变量导出到post-receive-log.txt。以下是搜索最新作业日志的循环:

find_job_of_commit() {
    local search_path=$1
    local searched_commit=$2
    echo "in loop search_path=$search_path" >> "post_receive_log.txt"
    echo "in loop searched_commit=$searched_commit" >> "post_receive_log.txt"
    query_result=$(while ! find "$search_path" -name "job.log" | xargs grep "Checking out $searched_commit"; do sleep 10 ; done)
    echo "query_result=$query_result" >> "post_receive_log.txt"
}

输出:

这会输出以下post_receive_log.txt

repopath_to_artifacts=/var/opt/gitlab/gitlab-rails/shared/artifacts/d4/73/d4735e3a265e16eee03f59718b9b5d03019c07d8b6c51f90da3a666eec13ab35
in loop search_path=/var/opt/gitlab/gitlab-rails/shared/artifacts/d4/73/d4735e3a265e16eee03f59718b9b5d03019c07d8b6c51f90da3a666eec13ab35
in loop searched_commit=eb052e7d

所以基本上可以断定post-receive 脚本在sleep 10 命令期间终止,或者它卡在while 循环中而无法找到文件。更详细的代码显示它实际上在sleep 10 命令之后停止。而且它没有找到最后一份工作(在这次运行中,最新的工作编号是31)。

但是,根据post_receive_log.txt 输出,我可以在 GitLab 泊坞窗内手动运行确切的等待命令,并且它确实工作:

root@127:/var/opt/gitlab/git-data/repositories/@hashed/d4/73/d4735e3a265e16eee03f59718b9b5d03019c07d8b6c51f90da3a666eec13ab35.git# while ! find "/var/opt/gitlab/gitlab-rails/shared/artifacts/d4/73/d4735e3a265e16eee03f59718b9b5d03019c07d8b6c51f90da3a666eec13ab35" -name "job.log" | xargs grep "Checking out eb052e7d"; do sleep 10 ; done
/var/opt/gitlab/gitlab-rails/shared/artifacts/d4/73/d4735e3a265e16eee03f59718b9b5d03019c07d8b6c51f90da3a666eec13ab35/2021_10_16/33/33/job.log:Checking out eb052e7d as master...

假设一

我认为repopath_to_artifacts 的文件路径中的@ 符号在命令行中的处理方式与在 bash 脚本中的处理方式不同,导致 bash 中的路径无效/不存在,但 CLI 中的路径有效。

假设二

所以我的第二个想法是 post-receive 在 GitLab 几秒钟后被终止。 4:Deadline Exceeded 消息证实了这一点:

假设三

find 命令使用某种不会在单个 shell 脚本中更新的目录图像。 (对我来说似乎不太可能,也没有解释为什么post-receive 脚本会停止)。但是,如果我手动(在 Docker 中)运行 post-receive 脚本,则手动测试证实了这一点:

/var/opt/gitlab/git-data/repositories/@hashed/d4/73/d4735e3a265e16eee03f59718b9b5d03019c07d8b6c51f90da3a666eec13ab35.git
/opt/gitlab/embedded/service/gitlab-shell/hooks/post-receive.d/./post-receive
f818b5eabfed71a70923bbf5186e31fc0806b6bc\n f818b5eabfed71a70923bbf5186e31fc0806b6bc\n repo_to_test_runner

这对于失败和成功的工作都适用。即使在 post-receive 作业未成功终止之后,在之前无法找到的提交上也是如此。

问题

为什么post-receive 文件会意外终止或卡在while 循环中?

【问题讨论】:

  • 在我看来你的整个脚本只是while ! find -name "job.log" | xargs grep "$commit"; do sleep 10 ; done。为什么find + 一些奇怪的'\n' + [[ ! -z grep?用 shellcheck 检查你的脚本!
  • 您的建议大大简化了代码。谢谢!代码仍会意外终止(或卡在 while 循环中),而手动运行命令确实会导致找到文件并终止 while 循环。你问的像 \n 这样的工件存在,因为我将包含多个文件路径的字符串拆分为一个数组,以调试每个扫描文件的 while 循环,并改为测试 for 循环,以防我的 condition 在 while 循环中导致问题。

标签: bash docker gitlab gitlab-ci git-post-receive


【解决方案1】:

假设 II 得到证实。接收后脚本在大约 60 秒后终止。我还不知道为什么。我通过每 2 秒记录一个输出来确定这一点,在它运行时查看日志文件并检查它何时停止产生输出。当4:Deadline Exceeded. 消息弹出时它就停止了,即使产生输出的调试 for 循环仍然需要进行 96 次迭代。

【讨论】:

    猜你喜欢
    • 2012-10-11
    • 2019-09-09
    • 1970-01-01
    • 1970-01-01
    • 2016-08-22
    • 1970-01-01
    • 2021-11-28
    • 1970-01-01
    • 2011-07-04
    相关资源
    最近更新 更多