Published on

解决 GitHub Action Runner 自动更新失败

Authors
  • Name

半个月前为了能自动 release 毕设论文,在服务器上装了 texlive 2020 和 GitHub Action Runner,并且写了个 service 文件跑了起来,今天 push 了一个新 tag 到 GitHub 上却收到邮件通知 “Run Failed”。


去 runner 的安装目录下发现它自动更新到了 2.262.1,而且目录下多了几个文件夹 bin.2.262.1/externals.2.262.1/,看日志发现上次服务退出之前报错了无数行

run.sh[647]: /etc/github-actions-runner/_work/_update.sh: line 31: nul: Permission denied

尝试重启服务也失败,日志说找不到 /etc/github-actions-runner/bin/Runner.Listener,再看发现目录下并没有 bin/,于是把 bin.2.262.1/ 软链到了 bin/,这下服务启动成功了,去 GitHub 运行 workflow 还是不行,回来又把 externals.2.262.1/ 也软链到了 externals/,再重启服务就能正常工作了。

是能用了,然而之前为什么会报错呢,整理好别的事情之后又回到服务器上看了一下这个 _update.sh 的内容,报错的那行的内容是

ping -c 2 127.0.0.1 >nul

但是整个文件夹和下面的所有文件都已经被 chown 到服务的运行用户 gh-action 了,没道理会没权限。自己用用户 gh-action 跑了一下 _update.sh,也是正常地运行起了 runner。由于这个 _update.sh 是实时被生成的,于是写了个监控脚本只要发现 _update.sh 被创建就把里面的 nul 改成绝对路径,然而再运行还是报 Permission denied

之后搜索到了 GitHub 官方关于自行创建服务的文档,文档里说需要用 RunnerRoot 下的 svc.sh 来管理服务,如果要自行创建 systemd 文件则需要按照这个模板来创建。看了一下模板文件,和自己写的文件区别在于 ExecStart 的文件不是 run.sh 而是 runsvc.sh,以及增加了 WorkingDirectory KillModeTimeoutStopSec

解决

拿各种组合分别跑了一下,得出结论是

  • Permission denied 是因为没有设置工作目录,添加
WorkingDirectory=${RunnerRoot}

可以解决。

  • 服务退出是由于 GitHub Action Runner 自动更新之后还要自动重启,默认的 KillModecontrol-group,会把所有的进程都关掉。加上
KillMode=process
KillSignal=SIGTERM

可以解决,代表只关闭主进程而不关闭子进程,这样才能正常执行 scheduled restart。

sshd 也是用的这种 KillMode,是为了防止用 ssh 连到服务器上执行 systemctl restart sshd 时把当前连接也关闭。 [ ref ]

  • 都加上之后就能正常运行服务了,但是去看状态显示的是 failed,然而 workflow 都在正常地跑着。怀疑是因为 ExecStart 用的是 run.sh 而不是模板里的 runsvc.sh。到 RunnerRoot 下也没找到这个文件,看到 svc.sh 里是从 ${RunnerRoot}/bin/ 下面复制出来的,于是试着跑了 ./svc.sh install gh-action 后,runsvc.sh 就出现了。看了一下生成的服务文件内容也很简单,和模板几乎完全一样。跑这个服务时就不会再出现之前的问题了,看状态也显示的是正常的 active (running)

  • 还有一个区别在于 TimeoutStopSec,模板里面用的是 5min,不写的话默认值是 90s,毕竟是停止超时时长,这项并不是前面问题的关键,所以直接用模板里的 5min 了。

最后把自己的服务文件删了,以后再有自己跑 GitHub Actions 的需求就用 svc.sh 安装服务吧,也不用麻烦自己去写了。