SCM-Manager 3.12.2 常用命令与运维详解
SCM-Manager 3.12.2 运维命令手册:systemd 服务管理、双路日志巡检、REST API 运维全集(认证、用户组、API Key、仓库生命周期、74 插件在线安装)、23MB 冷备与灾难恢复实测闭环、升级与 purge 数据去留实测,附 API Key 缺参、clone URL 新旧格式、307 全站重定向等排障实录。
SCM-Manager 3.12.2 常用命令与运维详解
本文面向 SCM-Manager 3.12.2 的日常运维与自动化管理:systemd 服务管理、双路日志巡检、REST API 运维命令全集(认证、用户/组、API Key、仓库生命周期、插件管理)、备份恢复闭环实测、升级卸载与数据去留实测,以及四个真实排障实录。除标注外全部为 Ubuntu 22.04.5 LTS 实测回显(2026-10-28)。配套阅读:安装指南、配置参数详解、介绍与选型指南。
一、服务管理(systemd)
1.1 启停与自启
# systemctl start scm-server # 启动
# systemctl stop scm-server # 停止
# systemctl restart scm-server # 重启(改配置/装插件后必需)
# systemctl is-enabled scm-server
enabled
# systemctl is-active scm-server
active
unit 关键定义(/etc/systemd/system/scm-server.service 实测):User=scm、Restart=on-failure(异常退出自动拉起)、SuccessExitStatus=143(容忍 SIGTERM 退出码)。Java 5~15 秒完成启动,stop 后立刻 start 时建议 sleep 2 避免端口占用竞态。
1.2 状态确认与进程画像
# systemctl status scm-server --no-pager | head -8
* scm-server.service - SCM-Manager Server
Loaded: loaded (/etc/systemd/system/scm-server.service; enabled; vendor preset: enabled)
Active: active (running) since Wed 2026-10-28 01:53:07 UTC; 7min ago
Main PID: 8547 (java)
Tasks: 48 (limit: 19553)
Memory: 284.0M
CPU: 9.851s
探活三件套(脚本化健康检查可直接用):
# curl -s -o /dev/null -w "%{http_code}\n" http://localhost:8080/scm/
200
# systemctl is-active scm-server
active
# ps -C java -o pid,rss,etime,cmd | tail -1
二、日志巡检
2.1 双路日志
SCM-Manager 同时产生两路日志:
- 应用日志
/var/log/scm/scm-manager.log(config.ymllog.logDir指定)——业务细节全在这里,grep "Startup token"、排障找ERROR都用它; - systemd 日志
journalctl -u scm-server——服务级事件(启停、退出码、systemd 侧错误):
# journalctl -u scm-server --no-pager -n 3
Oct 28 02:07:30 scm-lab systemd[1]: Stopped SCM-Manager Server.
Oct 28 02:07:30 scm-lab systemd[1]: scm-server.service: Consumed 8.506s CPU time.
Oct 28 02:07:30 scm-lab systemd[1]: Started SCM-Manager Server.
巡检命令组合:
# grep -c ERROR /var/log/scm/scm-manager.log # 错误计数
# tail -100 /var/log/scm/scm-manager.log | grep -E "ERROR|WARN" # 近百行告警
# grep "Started SCM-Manager\|start scm-manager version" /var/log/scm/scm-manager.log | tail -3
2.2 日志滚动与巡检要点
实测包内不带 /etc/logrotate.d 配置,运行期滚动由内置 appender 完成(实测日志目录出现 scm-manager-1.log 滚动文件,按大小滚动);若要按天轮转+压缩,需自建 /etc/logrotate.d/scm-server(对 /var/log/scm/*.log 配 daily、compress、copytruncate,copytruncate 避免 scm 用户文件句柄失效)。长期建议:生产环境把 config.yml rootLevel 锁定 WARN,DEBUG 仅临时排障(实测 DEBUG 模式数分钟即产生 MB 级日志)。
三、REST API 运维命令
SCM-Manager 提供覆盖全部管理功能的 Level 3 REST API(JSON),是脚本化运维的主通道。以下命令均实测通过,<认证会话> 获取见 3.1。
3.1 认证与会话
# curl -s -c /tmp/cookies.txt -X POST http://localhost:8080/scm/api/v2/auth/access_token \
> -H "Content-Type: application/json" -H "Accept: application/json, */*" \
> -d '{"cookie":true,"grant_type":"password","username":"scmadmin","password":"q1w2e3r4"}' \
> -o /dev/null -w "login:%{http_code}\n"
login:204
# curl -s -b /tmp/cookies.txt http://localhost:8080/scm/api/v2/me | head -c 120
{"name":"scmadmin","displayName":"SCM Administrator","mail":"scmadmin@example.com","groups":["_authenticated"]
登录成功 204,会话 Cookie 名为 X-Bearer-Token(JWT),后续请求 -b /tmp/cookies.txt 携带。会话有效期由 jwtExpirationInH 控制,过期后接口返回 401/307,重新登录即可。API 自动化建议改用 API Key(3.3 节)替代密码 Cookie。
3.2 用户与组管理
# curl -s -b /tmp/cookies.txt -X POST http://localhost:8080/scm/api/v2/users/ \
> -H "Content-Type: application/vnd.scmm-user+json;v=2" \
> -d '{"name":"dev01","displayName":"开发者一号","mail":"dev01@example.com","password":"dev01pass","active":true}' \
> -o /dev/null -w "user_create:%{http_code}\n"
user_create:201
# curl -s -b /tmp/cookies.txt -X POST http://localhost:8080/scm/api/v2/groups/ \
> -H "Content-Type: application/vnd.scmm-group+json;v=2" \
> -d '{"name":"developers","description":"开发组","members":["dev01"]}' \
> -o /dev/null -w "group_create:%{http_code}\n"
group_create:201
# curl -s -b /tmp/cookies.txt http://localhost:8080/scm/api/v2/users/dev01 | head -c 150
# curl -s -b /tmp/cookies.txt -X DELETE http://localhost:8080/scm/api/v2/users/dev01 -o /dev/null -w "user_del:%{http_code}\n"
创建/删除均返回 201/204;全局授权(/api/v2/permissions)与仓库级成员授权(PUT /api/v2/repositories/<ns>/<repo>/permissions/)按同风格调用。
3.3 API Key
# curl -s -b /tmp/cookies.txt -X POST http://localhost:8080/scm/api/v2/users/dev01/api_keys/ \
> -H "Content-Type: application/vnd.scmm-apiKey+json" \
> -d '{"displayName":"ci-token","email":"ci@example.com","permissionRole":"READ","expirationDate":"2027-10-28"}' \
> -w "\napikey_create:%{http_code}\n"
apikey_create:201
三个实测要点:① 必须带 permissionRole(READ/WRITE),缺省报 400,错误体明确提示 create.arg0.permissionRole: must not be empty(排障实录见 6.1);② 明文 token 只在创建响应中出现一次,需立即保存,之后仅能删除重建;③ 使用时以 Authorization: Bearer <token> 头替代 Cookie,适合 CI 长期任务。
3.4 仓库生命周期
# curl -s -b /tmp/cookies.txt -X POST http://localhost:8080/scm/api/v2/repositories/ \
> -H "Content-Type: application/vnd.scmm-repository+json;v=2" \
> -d '{"name":"demo-app","namespace":"scmadmin","type":"git","description":"运维实测演示仓库","contact":"scmadmin@example.com"}' \
> -o /dev/null -w "repo_create:%{http_code}\n"
repo_create:201
type 可选 git/hg/svn(本机实测装齐三类插件)。仓库落盘路径使用内部 ID(实测 /var/lib/scm/repositories/5SVZJ3GI73),不要直接改文件系统,一律走 API。
Git 推拉实测(URL 格式为 /scm/repo/<namespace>/<name>):
$ git clone http://scmadmin:<密码>@192.0.2.10:8080/scm/repo/scmadmin/demo-app
Cloning into 'demo-app'...
warning: You appear to have cloned an empty repository.
$ cd demo-app && echo "# demo" > README.md && git add . && git commit -m "init" -q && git push
To http://192.0.2.10:8080/scm/repo/scmadmin/demo-app
* [new branch] main -> main
推送后 API 验证:
# curl -s -b /tmp/cookies.txt http://localhost:8080/scm/api/v2/repositories/scmadmin/demo-app/branches/ | grep -o '"name":"main"'
"name":"main"
归档与删除:
# curl -s -b /tmp/cookies.txt -X POST http://localhost:8080/scm/api/v2/repositories/scmadmin/demo-app/archive -o /dev/null -w "archive:%{http_code}\n"
# curl -s -b /tmp/cookies.txt -X DELETE http://localhost:8080/scm/api/v2/repositories/scmadmin/demo-app -o /dev/null -w "repo_del:%{http_code}\n"
3.5 插件管理
# curl -s -b /tmp/cookies.txt http://localhost:8080/scm/api/v2/plugins/installed | grep -o '"name":"scm-[a-z-]*"'
# curl -s -b /tmp/cookies.txt "http://localhost:8080/scm/api/v2/plugins/available?page=0&pageSize=100" | grep -c '"name":"scm-'
74
# curl -s -b /tmp/cookies.txt -X POST http://localhost:8080/scm/api/v2/plugins/available/scm-readme-plugin/install -o /dev/null -w "install:%{http_code}\n"
install:200
# systemctl restart scm-server && sleep 15
# curl -s -b /tmp/cookies.txt http://localhost:8080/scm/api/v2/plugins/installed | grep -c '"name":"scm-'
5
实测流程:插件中心 74 个可装插件 → POST install 返回 200,.smp 包落盘 /var/lib/scm/plugins/ 并标记待重启 → 重启后激活(实测已装数从 4 变 5)。插件经应用层代理出网下载,离线环境可在 config.yml 配 proxyServer 或手动放置 .smp 包后重启。
四、备份与恢复(实测闭环)
4.1 冷备范围与打包
SCM-Manager 的全部状态集中在两处:数据目录 /var/lib/scm(SQLite 元数据 scm.db、仓库文件 repositories/、插件、索引)与两份配置(/etc/scm/config.yml、/etc/default/scm-server)。冷备标准流程(实测):
# systemctl stop scm-server
# tar -C / -czf /tmp/scm-backup-$(date +%F).tgz var/lib/scm etc/scm/config.yml etc/default/scm-server
# ls -lh /tmp/scm-backup-2026-10-28.tgz
-rw-r--r-- 1 root root 23M Oct 28 02:14 /tmp/scm-backup-2026-10-28.tgz
# systemctl start scm-server
实测 4 个仓库内小规模数据(1 仓库 1 用户 1 组 5 插件)备份包 23 MB。热备不推荐直接 tar 正在写的 SQLite(scm.db-wal 存在期间有截断风险);需热备请配合文件系统快照,或接受短暂停服做冷备。
4.2 灾难恢复验证
实测"清空数据目录 → 从备份恢复 → 全量验证":
# systemctl stop scm-server
# rm -rf /var/lib/scm/* # 灾难模拟
# tar -C / -xzf /tmp/scm-backup-2026-10-28.tgz
# chown -R scm:scm /var/lib/scm # 关键:恢复后必须修回属主
# systemctl start scm-server && sleep 15
# curl -s -o /dev/null -w "web:%{http_code}\n" http://localhost:8080/scm/
web:200
# curl -s -c /tmp/ck5 -X POST http://localhost:8080/scm/api/v2/auth/access_token -H "Content-Type: application/json" -H "Accept: application/json, */*" -d '{"cookie":true,"grant_type":"password","username":"scmadmin","password":"q1w2e3r4"}' -o /dev/null -w "login:%{http_code}\n"
login:204
# curl -s -b /tmp/ck5 http://localhost:8080/scm/api/v2/repositories/ | grep -o '"name":"demo-app"'
"name":"demo-app"
恢复闭环 100% 回归:Web 200、登录 204、仓库与用户数据完整。两个易错点:漏 chown -R scm:scm 会导致服务启动后读库失败;只备 /var/lib/scm 不备配置文件会导致恢复后监听口与堆参数回默认。
五、升级与卸载
5.1 升级
# systemctl stop scm-server
# tar -C / -czf /tmp/pre-upgrade-$(date +%F).tgz var/lib/scm etc/scm # 先冷备
# apt-get update && apt-get install --only-upgrade scm-server
预期结果:回显 Unpacking scm-server (新版本) ... Setting up ...,服务被 postinst 自动重启。跨版本升级时启动日志会出现 running update step for type ... 数据迁移序列(3.12.2 首启实测执行 12 个 update step),属正常现象,迁移完成前不要中断服务。
5.2 卸载与数据去留(实测)
# systemctl stop scm-server
# apt-get purge -y scm-server
Removing scm-server (3.12.2) ...
Purging configuration files for scm-server (3.12.2) ...
dpkg: warning: while removing scm-server, directory '/var/cache/scm/work' not empty so not removed
dpkg: warning: while removing scm-server, directory '/var/lib/scm' not empty so not removed
实测 purge 后的去留结论(逐路径核实):
| 路径 | 结果 |
|---|---|
/opt/scm-server(程序) | 删除 |
/etc/default/scm-server(启动配置) | 删除 |
/etc/scm/config.yml(硬链接服务层配置) | 删除 |
/var/lib/scm(全部仓库与元数据) | 保留(dpkg 明确提示 not empty so not removed) |
/var/log/scm、/var/cache/scm | 保留 |
即:purge 只删程序与包配置,代码仓库数据不会误删,需要彻底清除时手动 rm -rf /var/lib/scm /var/log/scm /var/cache/scm /etc/scm(先确认备份)。重新安装同版本包即可接回原数据目录。
六、排障实录汇总
6.1 API Key 创建 400:缺 permissionRole
现象:POST /api/v2/users/<user>/api_keys/ 返回 400,错误体(实测原样):
{"message":"input violates conditions (see violation list)","violations":[{"path":"create.arg0.permissionRole","message":"must not be empty"}]}
处置:body 补 "permissionRole":"READ"(或 WRITE)后 201 成功。
6.2 Git clone 用 /scm/git/ 旧格式报 not found
现象:git clone http://<user>:<pass>@<host>:8080/scm/git/<ns>/<repo> 报 repository ... not found(实测复现)。3.12.2 的 HTTP 协议链接为 /scm/repo/<ns>/<repo>(可从仓库详情 _links.protocol[0].href 获取)。处置:改用 /scm/repo/ 格式;不给 .git 后缀也能 clone。
6.3 forceBaseUrl 配错导致全站 307
现象:保存 baseUrl(不可达地址)+ forceBaseUrl: true 后,包括管理会话在内的所有请求被 307 强制跳转,Web 与 API 均失去入口。处置与完整恢复过程见《SCM-Manager 3.12.2 配置参数详解》第 4.2 节(curl --connect-to 映射回本机后重登修正)。
6.4 登录接口 400/406
POST /api/v2/auth/access_token 需同时满足:Content-Type: application/json、Accept 含 application/json、body 带 grant_type:"password"。缺 Accept 或 grant_type 时实测返回 400/406。标准请求模板见 3.1 节。
6.5 数据属主错乱
手动操作 /var/lib/scm(备份恢复、迁移)后若出现启动异常或登录后仓库 500,先查属主:ls -la /var/lib/scm 应全部为 scm:scm,chown -R scm:scm /var/lib/scm 后重启。