为何编辑gitlab-runsvdir服务文件可解决服务启动挂起问题?
问题场景
在本地Ubuntu服务器安装GitLab时,安装过程突然挂起,直到手动在后台执行/opt/gitlab/embedded/bin/runsvdir-start &才完成安装。重启机器后发现GitLab完全无法运行,查看gitlab-runsvdir.service状态显示已停止:
$ sudo systemctl status gitlab-runsvdir.service ○ gitlab-runsvdir.service - GitLab Runit supervision process Loaded: loaded (/usr/lib/systemd/system/gitlab-runsvdir.service; enabled; preset: enabled) Active: inactive (dead)
尝试执行启动命令:
sudo systemctl start gitlab-runsvdir.service
但命令直接卡住,只能用Ctrl-c终止,服务依旧处于停止状态。
排查过程
查阅了相关问题,但现有方案都依赖正常重启服务,而这正是当前的核心障碍,无法解决。随后查看服务的systemd配置文件,原内容如下:
[Unit] Description=GitLab Runit supervision process After=multi-user.target [Service] ExecStart=/opt/gitlab/embedded/bin/runsvdir-start Restart=always TasksMax=4915 [Install] WantedBy=multi-user.target
解决操作
之前从未接触过systemd配置文件,只是猜测可能存在启动顺序死锁,于是尝试注释掉After=multi-user.target,同时在[Service]段添加Type=simple,修改后的配置文件如下:
[Unit] Description=GitLab Runit supervision process # After=multi-user.target [Service] Type=simple ExecStart=/opt/gitlab/embedded/bin/runsvdir-start Restart=always TasksMax=4915 [Install] WantedBy=multi-user.target
修改后问题解决,服务能正常启动,GitLab也恢复运行。
原理分析
After=multi-user.target的作用
After=是systemd用来控制启动顺序的指令,它要求当前服务必须在multi-user.target这个目标单元启动完成后再启动。multi-user.target是systemd的核心目标之一,代表系统进入了多用户命令行模式,所有非图形界面的基础服务都已启动完毕。
为什么注释它能解决启动卡住的问题?
问题根源大概率是启动依赖循环死锁:
- 原配置要求
gitlab-runsvdir.service在multi-user.target之后启动,但multi-user.target的启动完成可能间接依赖某些GitLab相关的服务,而这些服务又需要gitlab-runsvdir.service来管理运行,形成了“你等我、我等你”的循环等待。 - 手动后台启动
runsvdir-start时,绕过了systemd的启动顺序限制,直接启动进程打破了死锁。注释After=multi-user.target后,systemd不再强制等待multi-user.target完成,而是直接启动该服务,避免了循环等待的场景。
Type=simple的作用
systemd服务的Type默认值就是simple,但显式声明更清晰。Type=simple表示ExecStart指定的进程就是服务的主进程,systemd会直接启动它,无需等待进程fork后台操作完成。而runsvdir-start本身是前台运行的进程(手动启动时需要加&放到后台),Type=simple正好匹配它的运行方式,确保systemd能正确识别服务的运行状态,不会因为进程模式不匹配导致启动卡住。
WantedBy=multi-user.target的含义
WantedBy=属于[Install]段的配置,它的作用是把当前服务关联到multi-user.target上——当系统启动到multi-user.target模式时,该服务会被自动拉起(实现开机自启)。这个配置本身没有问题,和启动时的卡住现象无关。
内容的提问来源于stack exchange,提问作者HerpDerpington

