fix(chv-muse-r12fix3-1): worker 开机时序竞态:Condition + path 触发,不赌重启预算(P6 缺口 ①)
R12 复测 2 钉死:剩下的 226 只点名 /home/chv/workspace——工作区由 cloud-final 的 chv-sync boot 克隆出来,晚于 multi-user.target 约 9 秒,worker 的 5 次启动预算在工作区出现前耗尽(5 台 VM 2 台 failed,手工 reset-failed + start 后立即 active,二进制无辜)。 修法三选一,选 (a)——让服务根本不在工作区出现前启动: 新单元 chv-gitea-worker.path(PathExists=/home/chv/workspace, 工作区一出现即触发启动)+ 服务加 ConditionPathExists=/home/chv/workspace(开机那次启动在命名空间 搭建之前干净跳过,不 226、不耗重启预算)。两者缺一不可: Condition 本身绝不重试,没有 .path 它就是一次跳过、服务永远不 起;只有 .path 而无 Condition,开机那次启动仍会在命名空间搭建 时 226 撞上限速。WantedBy=multi-user.target 保留(is-enabled 仍 为 enabled),runcmd 只启动 .path 单元(cloud-final 时工作区尚 未 clone,直接 start 服务会 226);.path 进 buildinfo contents 与两处 lockfile 登记,P6 预检由三件扩为四件。 不用 (b) 放宽 StartLimit:放宽只是把竞态窗口拉大,wake 时间在 负载下已翻倍(R12 复测 2),预算仍可能耗尽,仍是时序赌博。 不用 (c) 把工作区创建提前到 tmpfiles-setup 之前:/home/chv 本身 07:23:40 才出现(cloud-init 建 chv 用户),晚于 tmpfiles-setup (07:23:24);硬约束:绝不盲目补 tmpfiles 行。ExecStartPre 也不 行——命名空间搭建在它之前,救不了 226。 测试:WorkerUnitBootRaceTest 新增 8 项——Condition 在位、 StartLimit 未放宽(修法语义钉)、.path 触发配对(PathExists + WantedBy、无 Unit= 覆盖)、服务 WantedBy 保留、build.sh 启用 .path + runcmd 只起 .path、绝无工作区 tmpfiles 行、buildinfo 与 lockfile 登记;BuildInfoContentsTest 的 P6 件加 .path;P2/P4 干 跑夹具一并拷入 .path。P6/P2/P4 三模块 174 项全过。
This commit is contained in:
1 parent
7c517f7fcc
commit
e31354dc58
10 files changed
+165
-15
No files matched your search
+10
-4
@@ -216,8 +216,8 @@ if [ ! -f "$SCRIPT_DIR/chv-memory.py" ]; then
|
||||
echo "缺少 chv-memory.py(客内记忆文件脚本):$SCRIPT_DIR" >&2
|
||||
exit 1
|
||||
fi
|
||||
# 对齐 Muse P6:privsep worker / 薄客户端 / 单元三件缺一即失败。
|
||||
for p6_file in chv-gitea-worker.py chv-sync-worker-client.py chv-gitea-worker.service; do
|
||||
# 对齐 Muse P6:privsep worker / 薄客户端 / 单元 / 路径触发器四件缺一即失败。
|
||||
for p6_file in chv-gitea-worker.py chv-sync-worker-client.py chv-gitea-worker.service chv-gitea-worker.path; do
|
||||
if [ ! -f "$SCRIPT_DIR/$p6_file" ]; then
|
||||
echo "缺少 $p6_file(Muse P6 客机文件):$SCRIPT_DIR" >&2
|
||||
exit 1
|
||||
@@ -347,7 +347,12 @@ VC_ARGS=(-a "$OUT/disk.raw"
|
||||
--copy-in "$SCRIPT_DIR/chv-authd.service:/etc/systemd/system/"
|
||||
--run-command 'mv /usr/local/bin/authd.py /usr/local/bin/chv-authd && chmod +x /usr/local/bin/chv-authd /usr/local/bin/git-credential-chv-authd'
|
||||
--run-command 'systemctl enable chv-authd || true'
|
||||
--run-command 'printf "runcmd:\n - systemctl restart ssh || service ssh restart || true\n - systemctl start chv-authd || true\n - test -f /etc/chv/guest-env && chown chv:chv /etc/chv/guest-env || true\n - systemctl start chv-gitea-worker || true\n - /usr/local/bin/chv-sync boot >>/var/log/chv-sync.log 2>&1 || true\n" > /etc/cloud/cloud.cfg.d/99-chv-sync.cfg'
|
||||
# round-12 修复轮第三轮(缺口 ①):runcmd 只启动 .path 单元
|
||||
#(开机时它已由 enable 激活,这里是兜底),绝不直接 start 服务
|
||||
#——cloud-final 此时工作区尚未 clone,直接 start 服务会在命名
|
||||
# 空间搭建时 226;.path 单元在 boot 的 mkdir -p 建出工作区后
|
||||
# 才触发服务启动。
|
||||
--run-command 'printf "runcmd:\n - systemctl restart ssh || service ssh restart || true\n - systemctl start chv-authd || true\n - test -f /etc/chv/guest-env && chown chv:chv /etc/chv/guest-env || true\n - systemctl start chv-gitea-worker.path || true\n - /usr/local/bin/chv-sync boot >>/var/log/chv-sync.log 2>&1 || true\n" > /etc/cloud/cloud.cfg.d/99-chv-sync.cfg'
|
||||
--copy-in "$SCRIPT_DIR/chv-cdp-broker.py:/usr/local/bin/"
|
||||
--copy-in "$SCRIPT_DIR/chv_browser_guard.py:/usr/local/bin/"
|
||||
# round-12 修复轮(项 0):c3bf9fd 认领——browser-blocklist.txt
|
||||
@@ -365,8 +370,9 @@ VC_ARGS=(-a "$OUT/disk.raw"
|
||||
--copy-in "$SCRIPT_DIR/chv-gitea-worker.py:/usr/local/bin/"
|
||||
--copy-in "$SCRIPT_DIR/chv-sync-worker-client.py:/usr/local/bin/"
|
||||
--copy-in "$SCRIPT_DIR/chv-gitea-worker.service:/etc/systemd/system/"
|
||||
--copy-in "$SCRIPT_DIR/chv-gitea-worker.path:/etc/systemd/system/"
|
||||
--run-command 'mv /usr/local/bin/chv-gitea-worker.py /usr/local/bin/chv-gitea-worker && mv /usr/local/bin/chv-sync-worker-client.py /usr/local/bin/chv-sync-worker-client && chmod +x /usr/local/bin/chv-gitea-worker /usr/local/bin/chv-sync-worker-client'
|
||||
--run-command 'systemctl enable chv-gitea-worker || true'
|
||||
--run-command 'systemctl enable chv-gitea-worker chv-gitea-worker.path || true'
|
||||
|
||||
# round-11 真机修复(层 5):镜像不再设 credential.helper store
|
||||
#(authd helper 是唯一凭证 helper);P4 的 copy-in 行保留。
|
||||
|
||||
@@ -48,9 +48,11 @@ BASE_CONTENTS = [
|
||||
# 对齐 Muse P4:单元外 CDP broker + 浏览器安全共享模块 +
|
||||
# 静态拦截名单。
|
||||
"chv-cdp-broker", "chv-browser-guard", "browser-blocklist",
|
||||
# 对齐 Muse P6:privsep worker + 薄客户端 + 单元(无条件拷入)。
|
||||
# 对齐 Muse P6:privsep worker + 薄客户端 + 单元 + 路径触发器
|
||||
#(无条件拷入)。路径触发器是 round-12 修复轮第三轮缺口 ①
|
||||
# 的拉起机制(工作区出现才启动服务),与单元同款登记。
|
||||
"chv-gitea-worker", "chv-sync-worker-client",
|
||||
"chv-gitea-worker.service",
|
||||
"chv-gitea-worker.service", "chv-gitea-worker.path",
|
||||
|
||||
]
|
||||
|
||||
|
||||
@@ -49,10 +49,11 @@ DECLARED_SOURCES = {
|
||||
"chv-cdp-broker": "repo_commit",
|
||||
"chv-browser-guard": "repo_commit",
|
||||
"browser-blocklist": "repo_commit",
|
||||
# 对齐 Muse P6:worker 三件 + 叶子模块(privsep/safety)。
|
||||
# 对齐 Muse P6:worker 四件(+ 路径触发器)+ 叶子模块(privsep/safety)。
|
||||
"chv-gitea-worker": "repo_commit",
|
||||
"chv-sync-worker-client": "repo_commit",
|
||||
"chv-gitea-worker.service": "repo_commit",
|
||||
"chv-gitea-worker.path": "repo_commit",
|
||||
"cloud/chv/privsep.py": "repo_commit",
|
||||
"cloud/chv/checkout_detect.py": "repo_commit",
|
||||
"cloud/chv/safety.py": "repo_commit",
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
[Unit]
|
||||
Description=Start chv-gitea-worker once the sync workspace exists (feat-chv-muse-p6)
|
||||
# round-12 修复轮第三轮(缺口 ①):worker 的 ReadWritePaths 含
|
||||
# /home/chv/workspace,systemd 建 mount namespace 时该路径必须已
|
||||
# 存在;工作区由 cloud-final 的 chv-sync boot 克隆出来,晚于
|
||||
# multi-user.target 约 9 秒(R12 复测 2:worker 07:23:31 首启
|
||||
# 226,工作区 07:23:40.40 才出现,5 次启动预算同一秒内耗尽)。
|
||||
# 本单元只在工作区出现时触发服务启动——服务绝不在工作区出现前
|
||||
# 启动,命名空间搭建前即有保证。须与服务的 ConditionPathExists
|
||||
# 配对:Condition 挡住开机那次过早启动(干净跳过、不 226),本
|
||||
# 单元提供 Condition 本身没有的“出现后再试一次”。
|
||||
# 不用 StartLimit 放宽(仍是时序赌博,wake 时间在负载下已翻倍,
|
||||
# 预算仍可能耗尽)与 tmpfiles 补行(/home/chv 本身晚于
|
||||
# tmpfiles-setup,补了也没用),见服务单元 [Unit] 注释。
|
||||
|
||||
[Path]
|
||||
PathExists=/home/chv/workspace
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
||||
@@ -4,6 +4,20 @@ After=network-online.target chv-authd.service
|
||||
Wants=network-online.target
|
||||
# authd 是可选依赖:worker 的 git 经 P3 helper 向 authd 取凭证;
|
||||
# authd 没起来时 worker 的 git 调用直接拒绝,不静默用旧凭证。
|
||||
# 开机时序(round-12 修复轮第三轮,缺口 ①):工作区
|
||||
# /home/chv/workspace 由 cloud-final 的 chv-sync boot 克隆出来,
|
||||
# 晚于 multi-user.target 约 9 秒;而 ReadWritePaths 的路径必须在
|
||||
# systemd 建 mount namespace 时已存在,否则 226/NAMESPACE。
|
||||
# ConditionPathExists 让开机那次启动在工作区出现前干净跳过
|
||||
# (不耗重启预算、不 226);真正拉起靠 chv-gitea-worker.path
|
||||
# (工作区一出现即触发启动)。Condition 本身绝不重试——没有
|
||||
# .path 单元它就是一次跳过、服务永远不起;反过来只有 .path 而
|
||||
# 无 Condition,开机那次启动仍会在命名空间搭建时 226 撞上限速。
|
||||
# 两者缺一不可。StartLimit 不放宽:放宽只是把竞态窗口拉大,
|
||||
# wake 时间在负载下已翻倍(R12 复测 2),预算仍可能耗尽;
|
||||
# tmpfiles.d 也不补工作区行:/home/chv 本身 07:23:40 才出现,
|
||||
# 晚于 tmpfiles-setup(07:23:24),补了也没用。
|
||||
ConditionPathExists=/home/chv/workspace
|
||||
|
||||
[Service]
|
||||
Type=simple
|
||||
@@ -28,8 +42,10 @@ SystemCallFilter=@system-service
|
||||
# 下 systemd 建 mount namespace 的硬要求,缺一个即 226/NAMESPACE):
|
||||
# /run/chv-gitea 与 /var/log/chv-gitea-worker.log 由
|
||||
# /etc/tmpfiles.d/chv.conf 预建(build.sh 内联写,round-12 修复轮
|
||||
# 第二轮项 1);/home/chv/workspace 开机时已在(R12 复测的 226
|
||||
# 只报过前两处)。ExecStartPre 不能替代 tmpfiles.d——命名空间
|
||||
# 第二轮项 1);/home/chv/workspace 由 ConditionPathExists +
|
||||
# chv-gitea-worker.path 守门(round-12 修复轮第三轮缺口 ①,见
|
||||
# [Unit];R12 复测 2 钉死它才是剩下的 226——开机时序竞态,不要
|
||||
# 再写“开机时已在”)。ExecStartPre 不能替代 tmpfiles.d——命名空间
|
||||
# 搭建在它之前,226 发生在它运行之前。
|
||||
ReadWritePaths=/home/chv/workspace /run/chv-gitea /var/log/chv-gitea-worker.log
|
||||
# worker 崩溃不拖垮 agent:broker/薄 CLI 收到类型化失败即返回,
|
||||
|
||||
@@ -71,10 +71,11 @@ DECLARED_SOURCES = {
|
||||
"chv-cdp-broker": "repo_commit",
|
||||
"chv-browser-guard": "repo_commit",
|
||||
"browser-blocklist": "repo_commit",
|
||||
# 对齐 Muse P6:worker 三件 + 叶子模块(privsep/safety)。
|
||||
# 对齐 Muse P6:worker 四件(+ 路径触发器)+ 叶子模块(privsep/safety)。
|
||||
"chv-gitea-worker": "repo_commit",
|
||||
"chv-sync-worker-client": "repo_commit",
|
||||
"chv-gitea-worker.service": "repo_commit",
|
||||
"chv-gitea-worker.path": "repo_commit",
|
||||
"cloud/chv/privsep.py": "repo_commit",
|
||||
"cloud/chv/checkout_detect.py": "repo_commit",
|
||||
"cloud/chv/safety.py": "repo_commit",
|
||||
|
||||
@@ -633,7 +633,10 @@ class BuildDryRunTest(unittest.TestCase):
|
||||
# round-12 修复轮(项 2,P6):worker 三件亦
|
||||
# 是 build.sh 硬校验,夹具须一并拷入。
|
||||
"chv-gitea-worker.py", "chv-sync-worker-client.py",
|
||||
"chv-gitea-worker.service"):
|
||||
"chv-gitea-worker.service",
|
||||
# round-12 修复轮第三轮(缺口 ①):.path 单元
|
||||
# 亦是 P6 预检四件之一,夹具须一并拷入。
|
||||
"chv-gitea-worker.path"):
|
||||
shutil.copy2(ROOT / "chv-guest" / name,
|
||||
os.path.join(guest, name))
|
||||
shutil.copy2(ROOT / "host.py", os.path.join(repo, "host.py"))
|
||||
@@ -715,6 +718,7 @@ class BuildDryRunTest(unittest.TestCase):
|
||||
# 三件进镜像,干跑输出须含拷入与 enable。
|
||||
"chv-gitea-worker",
|
||||
"chv-gitea-worker.service",
|
||||
"chv-gitea-worker.path",
|
||||
"systemctl enable chv-gitea-worker",
|
||||
# round-12 修复轮(项 4,P10):结账检测
|
||||
# 模块进镜像,干跑输出须含条件拷入行。
|
||||
|
||||
@@ -859,7 +859,10 @@ class BuildDryRunTest(unittest.TestCase):
|
||||
# 是 build.sh 硬校验,夹具须一并拷入。
|
||||
"chv-gitea-worker.py",
|
||||
"chv-sync-worker-client.py",
|
||||
"chv-gitea-worker.service"):
|
||||
"chv-gitea-worker.service",
|
||||
# round-12 修复轮第三轮(缺口 ①):.path
|
||||
# 单元亦是 P6 预检四件之一,夹具须一并拷入。
|
||||
"chv-gitea-worker.path"):
|
||||
shutil.copy2(ROOT / "chv-guest" / name,
|
||||
os.path.join(guest, name))
|
||||
shutil.copy2(ROOT / "host.py", os.path.join(repo, "host.py"))
|
||||
@@ -920,6 +923,7 @@ class BuildDryRunTest(unittest.TestCase):
|
||||
# 三件进镜像,干跑输出须含拷入与 enable。
|
||||
"chv-gitea-worker",
|
||||
"chv-gitea-worker.service",
|
||||
"chv-gitea-worker.path",
|
||||
"systemctl enable chv-gitea-worker",
|
||||
# round-12 修复轮(项 4,P10):结账检测
|
||||
# 模块进镜像,干跑输出须含条件拷入行。
|
||||
|
||||
@@ -870,6 +870,93 @@ class WorkerUnitTmpfilesTest(unittest.TestCase):
|
||||
self.assertNotIn("ExecStartPre=", text)
|
||||
|
||||
|
||||
# -- (7c) worker 开机时序竞态:Condition + path 触发 ----------------------
|
||||
class WorkerUnitBootRaceTest(unittest.TestCase):
|
||||
"""round-12 修复轮第三轮(缺口 ①,P6):R12 复测 2 钉死剩下的
|
||||
226 只点名 /home/chv/workspace——工作区由 cloud-final 的
|
||||
chv-sync boot 克隆出来,晚于 multi-user.target 约 9 秒,worker
|
||||
的 5 次启动预算在工作区出现前耗尽。
|
||||
|
||||
修法选 (a)(Condition + systemd.path),不用 (b)/(c):
|
||||
- (a) 让服务根本不在工作区出现前启动:ConditionPathExists 把
|
||||
开机那次启动挡在命名空间搭建之前(干净跳过、不 226、不耗
|
||||
重启预算),.path 单元在工作区出现时再触发一次——Condition
|
||||
本身绝不重试,没有 .path 它就是一次跳过、服务永远不起。
|
||||
- (b) 放宽 StartLimit 只是把竞态窗口拉大:wake 时间在负载下
|
||||
已翻倍,预算仍可能耗尽,仍是时序赌博。
|
||||
- (c) 把工作区创建提前到 tmpfiles-setup 之前不可行:
|
||||
/home/chv 本身 07:23:40 才出现(cloud-init 建 chv 用户),
|
||||
晚于 tmpfiles-setup(07:23:24);硬约束:绝不盲目补
|
||||
tmpfiles 行。
|
||||
ExecStartPre 也救不了 226——命名空间搭建在它之前。
|
||||
"""
|
||||
|
||||
def _service_text(self):
|
||||
return (REPO_ROOT / "chv-guest"
|
||||
/ "chv-gitea-worker.service").read_text()
|
||||
|
||||
def _path_text(self):
|
||||
return (REPO_ROOT / "chv-guest"
|
||||
/ "chv-gitea-worker.path").read_text()
|
||||
|
||||
def _build_text(self):
|
||||
return (REPO_ROOT / "chv-guest" / "build.sh").read_text()
|
||||
|
||||
def test_service_gated_by_condition(self):
|
||||
self.assertIn(
|
||||
"ConditionPathExists=/home/chv/workspace",
|
||||
self._service_text())
|
||||
|
||||
def test_no_start_limit_widening(self):
|
||||
# 修法是 (a) 不是 (b):重启预算保持 systemd 默认,绝不
|
||||
# 靠放宽 StartLimit 赌工作区出现。
|
||||
text = self._service_text()
|
||||
self.assertNotIn("StartLimitBurst=", text)
|
||||
self.assertNotIn("StartLimitIntervalSec=", text)
|
||||
|
||||
def test_path_unit_triggers_on_workspace(self):
|
||||
text = self._path_text()
|
||||
self.assertIn("PathExists=/home/chv/workspace", text)
|
||||
self.assertIn("WantedBy=multi-user.target", text)
|
||||
# 不写 Unit=:默认触发同名 .service,与服务单元配对。
|
||||
self.assertNotIn("Unit=", text)
|
||||
|
||||
def test_service_still_wanted_by_multi_user(self):
|
||||
# WantedBy 保留:is-enabled 仍为 enabled;开机那次启动
|
||||
# 只会被 Condition 干净跳过,不会 226。
|
||||
self.assertIn("WantedBy=multi-user.target",
|
||||
self._service_text())
|
||||
|
||||
def test_build_enables_path_unit(self):
|
||||
text = self._build_text()
|
||||
self.assertIn("chv-gitea-worker.path:/etc/systemd/system/",
|
||||
text)
|
||||
self.assertIn(
|
||||
"systemctl enable chv-gitea-worker chv-gitea-worker.path",
|
||||
text)
|
||||
|
||||
def test_runcmd_starts_path_unit_not_service(self):
|
||||
text = self._build_text()
|
||||
self.assertIn("systemctl start chv-gitea-worker.path", text)
|
||||
# cloud-final 时工作区尚未 clone,直接 start 服务会 226。
|
||||
self.assertNotIn("systemctl start chv-gitea-worker || true",
|
||||
text)
|
||||
|
||||
def test_no_tmpfiles_line_for_workspace(self):
|
||||
# 硬约束:绝不盲目补 tmpfiles 行——/home/chv 本身晚于
|
||||
# tmpfiles-setup,补了也没用。
|
||||
self.assertNotIn("d /home/chv/workspace", self._build_text())
|
||||
|
||||
def test_buildinfo_and_lockfile_include_path_unit(self):
|
||||
self.assertIn("chv-gitea-worker.path",
|
||||
(REPO_ROOT / "chv-guest"
|
||||
/ "buildinfo.py").read_text())
|
||||
for name in ("check_lockfile.py", "generate_lockfile.py"):
|
||||
self.assertIn(
|
||||
'"chv-gitea-worker.path": "repo_commit"',
|
||||
(REPO_ROOT / "chv-guest" / name).read_text())
|
||||
|
||||
|
||||
class BuildInfoContentsTest(unittest.TestCase):
|
||||
"""round-12 修复轮(项 2,P6):worker 三件须进 BUILDINFO
|
||||
contents(无条件拷入,与 P2/P4 同款钉法)。"""
|
||||
@@ -900,7 +987,8 @@ class BuildInfoContentsTest(unittest.TestCase):
|
||||
out, "chv-guest-24.04-0.164.0-alpha.9-abc1234", "24.04",
|
||||
"0.164.0-alpha.9", "abc1234", "0" * 64, True, "1248")
|
||||
for item in ("chv-gitea-worker", "chv-sync-worker-client",
|
||||
"chv-gitea-worker.service"):
|
||||
"chv-gitea-worker.service",
|
||||
"chv-gitea-worker.path"):
|
||||
self.assertIn(item, info["contents"])
|
||||
|
||||
|
||||
|
||||
+10
-2
@@ -58,7 +58,13 @@ P3(authd/sentinel 本体——只读、不重写、不改接口)、不碰 P4
|
||||
单元外;`ProtectSystem=strict`、`PrivateTmp`、`NoNewPrivileges`、
|
||||
`CapabilityBoundingSet=` 空、`RestrictAddressFamilies=AF_UNIX AF_INET
|
||||
AF_INET6`、`SystemCallFilter=@system-service`、读写路径只限
|
||||
`/home/chv/workspace` 与 `/run/chv-gitea`)。
|
||||
`/home/chv/workspace` 与 `/run/chv-gitea`)。round-12 修复轮第三轮
|
||||
(缺口 ①):加 `ConditionPathExists=/home/chv/workspace`(开机那次
|
||||
启动在工作区出现前干净跳过、不 226)+ 新单元
|
||||
`chv-guest/chv-gitea-worker.path`(`PathExists=/home/chv/workspace`,
|
||||
工作区一出现即触发启动;两者缺一不可——Condition 本身绝不重试)。
|
||||
runcmd 只启动 .path 单元,不直接 start 服务;StartLimit 不放宽,
|
||||
tmpfiles.d 不补工作区行(见服务单元注释)。
|
||||
- `chv-guest/chv-sync-worker-client.py`(新,标准库薄客户端):
|
||||
`chv-sync pull/push/status` 在 worker socket 存在时改走 worker
|
||||
(发类型化请求、原样回显 worker 的 stdout/stderr、按 worker 的
|
||||
@@ -156,7 +162,9 @@ Base64、零宽字符)、藏在图片/附件/二进制里的指令、需要理
|
||||
## 4. 真机待验证清单(等测试机空闲,排队在 round-11 之后)
|
||||
|
||||
- worker 在 lite12 镜像里的启动时序(须在 broker/`chv-sync` 调用
|
||||
之前就绪;与 P3 authd 的启动顺序关系)。
|
||||
之前就绪;与 P3 authd 的启动顺序关系)。round-12 修复轮第三轮
|
||||
(缺口 ①)已改 Condition + .path 触发,待真机复测 3 验证 5 台
|
||||
VM 0 failed。
|
||||
- worker 的 systemd 沙箱在真机上生效(`systemctl status`、cgroup
|
||||
路径、受限调用被挡的表现)。
|
||||
- broker → worker → helper → authd → git 全链路在真机上跑通
|
||||
|
||||
Reference in new issue
Block a user