RhodeCode 4.27.1 常用 CLI 与运维命令详解
RhodeCode 4.27.1 运维命令实战手册:rccontrol 实例控制、supervisorctl 进程管理(含 4.1.0 tail 崩溃 bug 排障实录)、curl 直调 JSON-RPC API 的用户/权限/仓库全流程(含 grant_user_permission 更名坑)、建库/导入/备份/全文索引/日志排查;全部命令与回显在 Ubuntu 22.04.5 LTS 实测照抄。
RhodeCode 4.27.1 常用 CLI 与运维命令详解
目标:把 RhodeCode Community 4.27.1 在 Ubuntu 22.04.5 LTS 上日常运维要用到的命令一次讲清——rccontrol 实例控制端、supervisorctl 进程管理、curl 直调 JSON-RPC API(用户/权限/仓库)、仓库建库/导入/备份、日志与排障;全部命令与回显均在 Ubuntu 22.04.5 LTS 实测照抄,两条排障实录(API 方法更名坑、supervisorctl tail 崩溃 bug)完整沉淀。安装与环境准备见 《RhodeCode 4.27.1 Ubuntu 22.04 安装指南》,配置文件逐段解析见 《RhodeCode 4.27.1 配置参数详解》,产品定位与选型对比见 《RhodeCode 介绍与选型指南》。
一、环境信息
本文所有命令在以下环境实测(与 《RhodeCode 4.27.1 Ubuntu 22.04 安装指南》 的安装结果一致):
| 项目 | 值 |
|---|---|
| 操作系统 | Ubuntu 22.04.5 LTS |
| 应用版本 | RhodeCode Community 4.27.1(含 VCSServer 4.27.1) |
| 控制端 | rhodecode-control 1.24.4(rccontrol 命令) |
| 运行时 | Python 2.7.15(RhodeCode 自带运行时,随发行包安装) |
| 数据库 | PostgreSQL 14(本机 127.0.0.1:5432,库名/用户 rhodecode) |
| Community 实例 | community-1,监听 0.0.0.0:10020 |
| VCSServer 实例 | vcsserver-1,监听 127.0.0.1:10010 |
| supervisor 管理口 | 127.0.0.1:10000(inet_http_server) |
| 仓库存储根 | /var/opt/rhodecode/repos/ |
| 配置目录 | /root/.rccontrol/(实例)、/root/.rccontrol-profile/(控制端命令) |
| 示例账号 | admin / q1w2e3r4(管理员) |
两处 PATH 提醒(安装篇已说明,本文全部命令假定已生效):
# 控制端命令(rccontrol、supervisorctl)
export PATH=/root/.rccontrol-profile/bin:$PATH
# 实例自带工具(rhodecode-api、rhodecode-index、rc-ishell 等)
export PATH=/root/.rccontrol/community-1/profile/bin:$PATH
二、工具概览
RhodeCode 4.27.1 的运维命令分三组:控制端(/root/.rccontrol-profile/bin/)、实例工具(/root/.rccontrol/community-1/profile/bin/)、API 方法(走 HTTP JSON-RPC)。按用途归类如下。
2.1 服务与进程管理
| 命令 | 用途 | 常用形式 |
|---|---|---|
rccontrol status | 查看全部实例状态/版本/URL | rccontrol status |
rccontrol start/stop/restart | 按 实例名 启停单个实例 | rccontrol restart community-1 |
rccontrol self-stop | 停所有实例 + supervisord | rccontrol self-stop |
rccontrol upgrade | 升级指定实例(含 --offline) | rccontrol upgrade community-1 --offline |
supervisorctl | 细粒度进程管理(status/tail/pid…) | supervisorctl -c /root/.rccontrol/supervisor/supervisord.ini status |
rc-upgrade-db | 升级后执行数据库迁移 | rc-upgrade-db <实例 ini> |
2.2 API 客户端与自动化
| 命令 | 用途 | 常用形式 |
|---|---|---|
curl | 直调 JSON-RPC 端点 /_admin/api(本文主测) | 见「四」 |
rhodecode-api | 官方 API 命令行客户端(读 /root/.rhoderc) | rhodecode-api --instance-name=community-1 get_repos |
rhodecode-index | 构建 Whoosh 全文检索索引 | rhodecode-index --instance-name=community-1 |
rhodecode-list-instances | 列出实例与 API 连接信息 | rhodecode-list-instances |
2.3 仓库与内容维护
| 命令 | 用途 |
|---|---|
rhodecode-cleanup-repos | 清理已归档(软删除)仓库,支持 --older-than/--list-only |
rhodecode-cleanup-gists | 清理已删除 Gist,参数与上同 |
rhodecode-gist | 命令行创建/查看 Gist |
API rescan_repos | 仓库目录与数据库不同步时重新扫描登记 |
tar + pg_dump | 仓库目录 + 数据库双份备份(见 5.4) |
2.4 配置与调试
| 命令 | 用途 |
|---|---|
rhodecode-config | 渲染/更新 ini 配置(--update 改值后需重启实例) |
rc-ishell | 进入 IPython 交互式 shell,可直接调用 Python 层模型 |
rc-setup-app | 重新渲染实例配置模板(安装向导用) |
rc-add-artifact | 人工放置归档工件(如 license 文件) |
💡 版本说明:4.27.1 的 API 共 88 个方法,可用
get_method(不带参数)一次列出全部方法名,见 4.3。
三、服务与进程管理
RhodeCode 的进程模型是「supervisord 守护 → 两个 supervisor 程序组(community-1、vcsserver-1)→ 各跑一个 gunicorn」。rccontrol 是对 supervisor 的上层封装,日常看状态用 rccontrol,细粒度操作(tail、单进程重启)用 supervisorctl。
3.1 查看整体状态:rccontrol status
$ rccontrol status
RHODECODE CONTROL VERSION: 1.24.4
- NAME: community-1
- STATUS: RUNNING
logs: /root/.rccontrol/community-1/community.log
- VERSION: 4.27.1 Community
- VCS: vcsserver-1
- URL: http://0.0.0.0:10020
- CONFIG: /root/.rccontrol/community-1/rhodecode.ini
- NAME: vcsserver-1
- STATUS: RUNNING
logs: /root/.rccontrol/vcsserver-1/vcsserver.log
- VERSION: 4.27.1 VCSServer
- URL: http://127.0.0.1:10010
- CONFIG: /root/.rccontrol/vcsserver-1/vcsserver.ini
rccontrol --help 列出的全部子命令(实测回显):
Commands:
enable-module Enables additional modules.
import Imports your current RhodeCode instance.
install Installs the specified RhodeCode application.
ishell Starts the specified application iShell interface
license Display license information.
restart Restarts the specified application instance.
self-destroy Completely removes rccontrol and any instances installed
on...
self-init Initializes rccontrol and supervisord on your server.
self-stop Stops all instances and supervisord.
self-update Retrieves the latest version information and upgrades...
start Starts the specified application instance.
status Displays the status of installed application instances.
stop Stops the specified application instance.
uninstall Uninstalls the specified application instance.
upgrade Upgrades the specified application instance.
3.2 supervisorctl 细粒度管理
supervisorctl 必须带 -c 指向 supervisord 配置(认证信息写在配置里,无需手工输密码):
SC="supervisorctl -c /root/.rccontrol/supervisor/supervisord.ini"
查看状态、进程号、supervisor 版本(实测回显):
$ $SC status
community-1:community-1_script RUNNING pid 10070, uptime 0:09:35
vcsserver-1:vcsserver-1_script RUNNING pid 8813, uptime 0:30:12
$ $SC pid community-1:community-1_script
10070
$ $SC version
4.1.0
💡 程序名必须带组前缀
组名:程序名(community-1:community-1_script)。supervisord 配置里每个实例是[group:community-1]包着[program:community-1_script],裸写community-1_script会报 no such process。
重启单个实例(实测:pid 从 10070 变为 10667):
$ $SC restart community-1:community-1_script
community-1:community-1_script: stopped
community-1:community-1_script: started
$ $SC status
community-1:community-1_script RUNNING pid 10667, uptime 0:00:07
vcsserver-1:vcsserver-1_script RUNNING pid 8813, uptime 0:33:12
stop → start 闭环(实测对 vcsserver-1 操作,STOPPED 状态会显示停止时间):
$ $SC stop vcsserver-1:vcsserver-1_script
vcsserver-1:vcsserver-1_script: stopped
$ $SC status
community-1:community-1_script RUNNING pid 10667, uptime 0:02:38
vcsserver-1:vcsserver-1_script STOPPED Oct 28 01:55 AM
$ $SC start vcsserver-1:vcsserver-1_script
vcsserver-1:vcsserver-1_script: started
$ $SC status
community-1:community-1_script RUNNING pid 10667, uptime 0:02:43
vcsserver-1:vcsserver-1_script RUNNING pid 10950, uptime 0:00:05
与 rccontrol 的关系:rccontrol restart community-1 等价于对组做 stop/start,效果相同;差异在 rccontrol self-stop 会把 supervisord 一并停掉(配合 systemd 托管时才是正确的整机停止方式,见安装篇)。
3.3 排障实录一:supervisorctl tail 崩溃(AttributeError)
按 supervisor 官方语法,tail <name> <bytes> 应输出日志尾部,但在本环境(非交互 shell、redirect_stderr=true)实测直接崩溃:
$ $SC tail community-1:community-1_script
error: <type 'exceptions.AttributeError'>, 'NoneType' object has no attribute 'lower': file: /opt/rhodecode/store/4wp0lvs7cb4zaxmpxc6vbiz0cspfa85a-python2.7-supervisor-4.1.0/lib/python2.7/site-packages/supervisor/supervisorctl.py line: 440
$ $SC tail community-1:community-1_script 500
Error: bad channel '500'
两个回显对应两个原因:
- 崩溃 bug(line 440):supervisor 4.1.0 的
supervisorctl.py在do_tail入口调用check_encoding(),其实现为:
def not_all_langs():
enc = getattr(sys.stdout, 'encoding', '').lower()
return None if enc.startswith('utf') else sys.stdout.encoding
非交互方式运行(输出经管道/重定向)时 sys.stdout.encoding 是 None 而非空串,getattr 拿到 None 后 .lower() 直接 AttributeError——getattr 的默认值 '' 根本兜不住。这是 supervisor 4.1.0 的已知缺陷,交互 tty 下不触发。
bad channel '500':4.1.0 的do_tail参数解析为tail [-f] <name> [stdout|stderr],第二个位置参数只认stdout/stderr通道名;截取字节长度的语法是修饰符tail -N <name>,不是tail <name> N(旧版 supervisor 的差异点)。
绕过方案(实测有效):给 stdout 一个编码即可跳过崩溃路径,再按正确语法取日志:
$ export PYTHONIOENCODING=utf-8
$ $SC tail -300 community-1:community-1_script
ode.lib.middleware.request_wrapper] Req[ 1] <AuthUser('id:2[admin] ip:127.0.0.1 auth:False')> POST Request to /_admin/api time: 0.0977s [curl/7.81.0], RhodeCode 4.27.1
2026-10-28 01:52:43.560 <10682> INFO [GNCRN] 127.0.0.1 rqt:0.099070 200 101 "POST:/_admin/api " usr:- "-" "curl/7.81.0"
脚本化运维建议直接读日志文件(见「六」),完全绕开该 bug。
四、用户与权限 API 调用(curl JSON-RPC 实测)
RhodeCode 所有管理操作都有同名 API 方法,端点为 http://<host>:10020/_admin/api,JSON-RPC 2.0 格式,鉴权用 API token(管理员在 Web 界面 Profile → Auth Tokens 生成;实例安装后首个 admin 的 token 也写入了 /root/.rhoderc)。本节全部实测。
4.1 调用骨架与身份验证
curl 请求骨架(auth_token 换成你的 token):
curl -s -X POST http://127.0.0.1:10020/_admin/api \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"auth_token":"<API_TOKEN>","method":"<方法名>","args":{}}'
/root/.rhoderc 内容(rhodecode-api 客户端的默认配置,安装时自动生成):
[instance:community-1]
api_key = c0a9afc7efae6c280f5aa07ea2c8fe1afe9020ec
api_host = http://127.0.0.1:10020
token 错误时的真实回显:
{
"id": 20,
"error": "Invalid API KEY",
"result": null
}
4.2 get_user:查用户与其权限摘要
$ curl -s -X POST http://127.0.0.1:10020/_admin/api \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"auth_token":"c0a9afc7efae6c280f5aa07ea2c8fe1afe9020ec","method":"get_user","args":{"userid":"admin"}}' | python3 -m json.tool
(回显节选——permissions_summary.global 里的 hg.admin 即超级管理员全局权限):
{
"result": {
"permissions_summary": {
"repositories": {
"demo-project": "repository.admin"
},
"global": [
"hg.admin",
"hg.create.write_on_repogroup.true"
],
"repository_branches": {},
"user_groups": {},
"repositories_groups": {}
},
"user_id": 2,
"last_activity": "2026-10-28T00:58:29.417",
"email": "admin@rhodecode.local",
"extern_type": "rhodecode",
"admin": true,
4.3 get_method:查方法签名与全部方法名
查某个方法的定义(返回该方法的 docstring、参数 schema):
$ curl -s -X POST http://127.0.0.1:10020/_admin/api \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":2,"auth_token":"c0a9afc7efae6c280f5aa07ea2c8fe1afe9020ec","method":"get_method","args":{"name":"create_repo"}}' | python3 -m json.tool
不带 name 参数则列出全部方法名(实测共 88 个,节选):
{
"result": [
"changeset_comment",
"get_locks",
"show_ip",
"create_gist",
"delete_gist",
"get_gist",
"get_gists",
"close_pull_request",
"comment_pull_request",
"create_pull_request",
"get_pull_request",
"get_pull_request_comments",
"get_pull_requests",
"merge_pull_request",
"update_pull_request",
"add_field_to_repo",
"comment_commit",
"create_repo",
"delete_repo",
"fork_repo",
"get_comment",
"get_repo",
4.4 create_user:建用户
$ curl -s -X POST http://127.0.0.1:10020/_admin/api \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":5,"auth_token":"c0a9afc7efae6c280f5aa07ea2c8fe1afe9020ec","method":"create_user","args":{"username":"opsuser","password":"q1w2e3r4","email":"opsuser@rhodecode.local","firstname":"Ops","lastname":"User","active":true}}' | python3 -m json.tool
(回显节选——新用户 user_id: 3、admin: false):
{
"result": {
"user": {
"user_id": 3,
"last_activity": null,
"email": "opsuser@rhodecode.local",
"extern_type": "rhodecode",
"admin": false,
4.5 排障实录二:给仓库授权的正确方法名是 grant_user_permission
按老版本文档给仓库授权,方法名写 grant_user_permission_to_repo,4.27.1 实测直接报错——但报错信息本身就附了近似方法提示,非常有用:
{
"result": null,
"error": "No such method: grant_user_permission_to_repo. Similar methods: grant_user_group_permission, grant_user_permission, grant_user_group_permission_to_repo_group, grant_user_permission_to_repo_group, ...",
"id": 6
}
到实例源码里确认(rhodecode/api/views/repo_api.py,4.27.1 实际代码):
@jsonrpc_method()
def grant_user_permission(request, apiuser, repoid, userid, perm):
即 4.27.1 里"给用户授予仓库权限"的方法名就是 grant_user_permission(签名为 repoid + userid + perm,作用对象是仓库;同理 grant_user_group_permission 是给用户组授仓库权限)。正确调用:
$ curl -s -X POST http://127.0.0.1:10020/_admin/api \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":8,"auth_token":"c0a9afc7efae6c280f5aa07ea2c8fe1afe9020ec","method":"grant_user_permission","args":{"repoid":"ops-d1-demo","userid":"opsuser","perm":"repository.write"}}' | python3 -m json.tool
{
"result": {
"success": true,
"msg": "Granted perm: `repository.write` for user: `opsuser` in repo: `ops-d1-demo`"
},
"error": null,
"id": 8
}
授权后用 get_repo 回查(节选,可见两条权限来源:owner 与显式授权):
"permissions": [
{
"origin": "owner",
"name": "admin",
"permission": "repository.admin",
"type": "user"
},
{
"origin": "permission",
常用仓库级权限取值:repository.none / repository.read / repository.write / repository.admin;撤销用 revoke_user_permission(参数同为 repoid + userid)。
4.6 rhodecode-api 命令行客户端
同一 API 也可用官方 CLI 客户端调用,它读 /root/.rhoderc 里的 api_key/api_host,输出已格式化:
$ rhodecode-api --instance-name=community-1 get_repos
{
"error": null,
"id": 7147,
"result": [
{
"clone_uri": "",
"created_on": "2026-10-28T00:58:19.262",
"description": "CLI demo repo",
...
"owner": "admin",
"private": true,
"repo_id": 1,
"repo_name": "demo-project",
"repo_type": "git",
"url": "http://127.0.0.1:10020/demo-project"
}
]
配套的 rhodecode-list-instances 可列出实例与 API 连接参数(脚本里可用来动态取 key):
$ rhodecode-list-instances
[instance:community-1] - Config only
API-HOST: http://127.0.0.1:10020
API-KEY: c0a9afc7efae6c280f5aa07ea2c8fe1afe9020ec
五、仓库运维(建库 / 导入 / 备份)
5.1 API 建库:create_repo
$ curl -s -X POST http://127.0.0.1:10020/_admin/api \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":4,"auth_token":"c0a9afc7efae6c280f5aa07ea2c8fe1afe9020ec","method":"create_repo","args":{"repo_name":"ops-d1-demo","repo_type":"git","description":"D1 CLI lab repo","private":true}}' | python3 -m json.tool
{
"result": {
"task": null,
"success": true,
"msg": "Created new repository `ops-d1-demo`"
},
"error": null,
"id": 4
}
重名时报错回显(args.repo_name 冲突检测在前端与 API 双侧生效):
{
"id": 21,
"error": {
"unique_repo_name": "Repository with name `ops-d1-demo` already exists"
},
"result": null
}
建库后磁盘上出现对应目录(/var/opt/rhodecode/repos/,下划线替换斜杠):
$ ls /var/opt/rhodecode/repos/
demo-project
ops-d1-demo
5.2 HTTP 导入既有仓库:clone + push
空库可直接 clone 后提交推送(管理员账号走 HTTP Basic 认证,实测完整回显):
$ git clone http://admin:q1w2e3r4@127.0.0.1:10020/ops-d1-demo
Cloning into 'ops-d1-demo'...
warning: You appear to have cloned an empty repository.
$ cd ops-d1-demo
$ git config user.email ops@lab.local && git config user.name ops
$ echo "D1 lab import" > README.md
$ git add . && git commit -m "D1 import commit"
1 file changed, 1 insertion(+)
create mode 100644 README.md
$ git push origin master
remote: RhodeCode: open pull request link: http://127.0.0.1:10020/ops-d1-demo/pull-request/new?branch=master
remote: RhodeCode: push completed
To http://127.0.0.1:10020/ops-d1-demo
* [new branch] master -> master
导入既有 Git 库的套路:git clone --mirror <旧地址> 后 git push --mirror http://admin:q1w2e3r4@<host>:10020/<库名>;SVN/Mercurial 迁移可先 git svn clone / hg convert 转成 Git 再走同一通道(产品本身也原生托管 hg/svn 库,直接 create_repo 指定 repo_type 后向对应 URL push 即可)。
5.3 仓库目录与数据库对账:rescan_repos
手工往 /var/opt/rhodecode/repos/ 拷贝过裸仓库、或磁盘与登记不一致时,调用 rescan 实测:
$ curl -s -X POST http://127.0.0.1:10020/_admin/api \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":11,"auth_token":"c0a9afc7efae6c280f5aa07ea2c8fe1afe9020ec","method":"rescan_repos","args":{"remove_obsolete":false}}' | python3 -m json.tool
{
"id": 11,
"error": null,
"result": {
"added": [],
"removed": []
}
}
⚠️
remove_obsolete: true会把数据库中没有登记的磁盘目录直接删除,生产环境先跑false看差异。
5.4 备份:pg_dump + tar 双份
数据库(PostgreSQL 14,custom 格式便于 pg_restore --list 抽查):
# postgres 系统用户执行 pg_dump;/root 属主为 root,先落 /tmp 再移入备份目录
$ su postgres -c "pg_dump -d rhodecode -F c -f /tmp/rhodecode-d1.dump"
$ mv /tmp/rhodecode-d1.dump /root/backup/
$ pg_restore --list /root/backup/rhodecode-d1.dump | head -8
;
; Archive created at 2026-10-28 01:52:05 UTC
; dbname: rhodecode
; TOC Entries: 486
; Compression: -1
; Dump Version: 1.14-0
; Format: CUSTOM
; Integer: 4 bytes
仓库目录(版本库文件本体,与数据库各含一半真相——数据库存元数据/PR/权限,repos 目录存版本历史,两者都要备):
$ tar -C /var/opt/rhodecode -czf /root/backup/repos-d1.tar.gz repos
$ ls -la /root/backup/
-rw-r--r-- 1 root root 4002 Oct 28 01:51 repos-d1.tar.gz
-rw-rw-r-- 1 postgres postgres 192608 Oct 28 01:52 rhodecode-d1.dump
$ tar -tzf /root/backup/repos-d1.tar.gz | head -4
repos/
repos/.rc_gist_store/
repos/.rc_gist_store/1/
repos/.rc_gist_store/1/.hg/
恢复演练要点:先 pg_restore -d rhodecode <dump> 回灌数据库,再把 repos 目录解回 /var/opt/rhodecode/,最后调一次 rescan_repos(5.3)对账。
5.5 全文检索索引:rhodecode-index
Whoosh 索引默认存 %(here)s/data/index(即 /root/.rccontrol/community-1/data/index,search.location 参数,见配置篇)。手工重建索引实测:
$ rhodecode-index --instance-name=community-1 \
--api-key=c0a9afc7efae6c280f5aa07ea2c8fe1afe9020ec \
--api-host=http://127.0.0.1:10020
PROCESSED [demo-project] 1/2 repo process limit:-1
FETCH [ops-d1-demo] repository configuration
FETCH [ops-d1-demo] repository configuration [done in: 0.068s]
FETCH [ops-d1-demo] commit info (1000 commits per call. Server reported 1 total commits, process limit is 10000)
Fetched 1000 commits [1 total][fetch:0001]
FETCH [ops-d1-demo] commit info [done in: 0.056s]
FETCH [ops-d1-demo] file tree info (@commit_id: branch:master:`3bed239f`) [1 done in: 0.067s]
FILES [ops-d1-demo] marked for indexing: 1
FILES [ops-d1-demo] marked for re-indexing: 0
FILES [ops-d1-demo] marked for removal: 0
FETCH [ops-d1-demo] file content info (@path `README.md` @commit_id: `3bed239f`) [1 done in: 0.040s]
PROCESSED [ops-d1-demo] 2/2 repo process limit:-1
>>> FINISHED BUILDING INDEX <<<
定时任务建议(夜间增量):rhodecode-index --instance-name=community-1 --index-update 配 cron;全量重建直接去掉该参数。改了 search_mapping.ini(配置篇有解析)后需全量重建。
5.6 软删除清理:rhodecode-cleanup-repos
Web/API 删除的仓库默认进"归档"状态(目录移入存档区等待清理),定期清实测清单:
$ rhodecode-cleanup-repos --instance-name=community-1 --list-only -R /var/opt/rhodecode/repos
常用参数:--older-than=30d(只清归档超过 30 天的)、--dont-ask(脚本化免确认)、--include-groups(连同仓库组)。Gist 对应 rhodecode-cleanup-gists,参数一致。
六、日志与排障
6.1 日志文件清单与查看
| 文件 | 内容 | 看什么 |
|---|---|---|
/root/.rccontrol/community-1/community.log | Community 应用日志(stdout_logfile,含访问行) | HTTP 请求、慢请求、异常栈、API 调用 |
/root/.rccontrol/vcsserver-1/vcsserver.log | VCSServer 日志 | clone/push 后端错误 |
/root/.rccontrol/supervisor/supervisord.log | supervisor 生命周期日志 | 进程拉起/退出、BACKOFF/FATAL |
应用日志格式(时间 <pid> 级别 [组件] 内容;每个 HTTP 请求两行——request_wrapper 摘要 + 访问行):
$ tail -8 /root/.rccontrol/community-1/community.log
2026-10-28 01:52:28.833 [10682] INFO [rhodecode.model] RhodeCode 4.27.1 initializing db for postgresql://rhodecode:XXXXX@127.0.0.1:5432/rhodecode
2026-10-28 01:52:28.835 [10682] INFO [rhodecode.config.environment] Enabled VCS backends: ['hg', 'git', 'svn']
2026-10-28 01:52:30.637 [10680] INFO [rhodecode.config.middleware] Pyramid app `pyramid_app_with_cleanup` created and configured in 2.19s
2026-10-28 01:52:30.648 [10681] INFO [rhodecode.config.middleware] Pyramid app `pyramid_app_with_cleanup` created and configured in 2.34s
2026-10-28 01:52:30.648 [10678] INFO [rhodecode.config.middleware] Pyramid app `pyramid_app_with_cleanup` created and configured in 2.47s
2026-10-28 01:52:30.670 [10679] INFO [rhodecode.config.middleware] Pyramid app `pyramid_app_with_cleanup` created and configured in 2.32s
2026-10-28 01:52:30.807 [10683] INFO [rhodecode.config.middleware] Pyramid app `pyramid_app_with_cleanup` created and configured in 2.20s
2026-10-28 01:52:30.872 [10682] INFO [rhodecode.config.middleware] Pyramid app `pyramid_app_with_cleanup` created and configured in 2.06s
supervisor 生命周期(restart 前后):
$ tail -5 /root/.rccontrol/supervisor/supervisord.log
2026-10-28 01:39:58,813 INFO success: community-1_script entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)
2026-10-28 01:52:24,774 INFO waiting for community-1_script to stop
2026-10-28 01:52:25,785 INFO stopped: community-1_script (exit status 0)
2026-10-28 01:52:25,788 INFO spawned: 'community-1_script' with pid 10667
2026-10-28 01:52:26,790 INFO success: community-1_script entered RUNNING state, process has stayed up for > than 1 seconds (startsecs)
💡 两个实例的
redirect_stderr = true:gunicorn 的错误输出与应用日志同文件;交互式 tty 里也可用supervisorctl tail -f community-1:community-1_script实时跟踪(注意 3.3 的崩溃 bug 与绕过)。
6.2 API 调用日志核对
每次 API 调用在 community.log 里都有两行记录,可用来核对脚本是否真正到达服务端(status code / 耗时 / UA):
... Req[ 1] <AuthUser('id:2[admin] ip:127.0.0.1 auth:False')> POST Request to /_admin/api time: 0.0977s [curl/7.81.0], RhodeCode 4.27.1
2026-10-28 01:52:43.560 <10682> INFO [GNCRN] 127.0.0.1 rqt:0.099070 200 101 "POST:/_admin/api " usr:- "-" "curl/7.81.0"
6.3 交互式调试:rc-ishell
IPython 风格 shell,已加载应用环境(UserModel 等模型可直接用),适合 SQL/ORM 层面的核查;管道喂入实测:
$ echo 'from rhodecode.model.user import UserModel; print("ishell ok, version:", __import__("rhodecode").__version__)' | rc-ishell /root/.rccontrol/community-1/rhodecode.ini
In [1]: ('ishell ok, version:', '4.27.1')
6.4 rhodecode-config 的边界
rhodecode-config --update --filename=<ini> [段]键=值 可改配置(改完须重启实例生效);但 --show 在 4.27.1 实测并不可靠——对 ini 中存在的键返回空 {},对不存在的键直接抛 KeyError(如 KeyError: u'instance_title',CE 默认模板本就无此键)。因此读配置建议直接 grep ini 文件,写配置用 --update 或编辑器改完重启:
$ grep -n "search.location" /root/.rccontrol/community-1/rhodecode.ini
473:search.location = %(here)s/data/index
6.5 常见故障速查
| 现象 | 定位 | 处置 |
|---|---|---|
rccontrol status 显示 FATAL/BACKOFF | supervisord.log 看退出原因,community.log 看异常栈 | 常见为数据库未就绪/端口占用,修复后 $SC start 组名:程序名 |
| Web 502 | nginx 已通但 gunicorn 未监听 | 看 ss -lntp | grep 10020,restart community-1 |
API 返回 Invalid API KEY | token 过期/复制错 | Web 界面重新生成,同步更新 /root/.rhoderc |
API 返回 No such method | 方法名不匹配 4.27 命名 | 用报错附带的 Similar methods 或 get_method 兜底(见 4.5) |
| push 卡住/超时 | VCSServer 没起来 | $SC status 确认 vcsserver-1,restart 后重试 |
| 搜索无结果 | 索引未建/键值变化 | 重跑 rhodecode-index(5.5) |
| 新建仓库在界面缺失 | 磁盘与 DB 不同步 | rescan_repos(5.3) |
七、FAQ
Q1:admin 的 API token 去哪里找?
A:实例安装完成后写入 /root/.rhoderc(api_key 行);也可在 Web 界面右上角头像 → Profile → Auth Tokens 查看/生成新 token。本文所有 curl 示例中的 token 即取自该文件。
Q2:改了配置/权限为什么不生效?
A:权限变更实时生效无需重启;rhodecode.ini 的配置变更需重启实例(rccontrol restart community-1 或 $SC restart community-1:community-1_script)。gunicorn 配置(worker 数等)改动同样走重启。
Q3:脚本能用什么语言调 API?
A:任何能发 HTTP POST 的语言均可,协议是标准 JSON-RPC 2.0(字段 jsonrpc/id/method/args,鉴权 auth_token)。批量操作建议串行小步提交并检查每笔 error 字段;88 个方法全清单用 get_method(不带参数)拉取。
Q4:备份只需备 repos 目录吗?
A:不够。数据库(用户/权限/PR/issue/审计)与 repos 目录(版本历史)各存一半,5.4 的 pg_dump + tar 双份都要做;第三方 Git 托管工具(如 gitea/gitlab)的裸仓库迁移进 RhodeCode 前,先在测试实例演练 create_repo → push --mirror → rescan_repos 流程。
Q5:如何安全地做整机重启?
A:rccontrol self-stop → 重启服务器 → rccontrol self-init(supervisord 未托管时)或依赖 systemd 单元自启(安装篇的 unit 已配置 ExecStop=supervisorctl ... shutdown)。不要直接 kill gunicorn,supervisor 会按退避策略反复拉起造成双实例。
Q6:rhodecode-api 与 curl 直调该用哪个?
A:临时查询/调试用 rhodecode-api(免拼 JSON、输出已格式化,读 /root/.rhoderc);脚本与自动化用 curl 直调(可控超时、可解析 error 结构、便于并发管理)。二者走同一端点同一鉴权,结果一致。
Q7:supervisorctl tail 一用就崩是坏了吗?
A:不是。supervisor 4.1.0 的已知编码检查 bug(见 3.3 排障实录):非交互 stdout 下 sys.stdout.encoding 为 None 触发 AttributeError。交互终端直接可用;脚本环境加 export PYTHONIOENCODING=utf-8 或改为读日志文件。
本文全部命令于 2026-10-28 在 Ubuntu 22.04.5 LTS(RhodeCode Community 4.27.1 / VCSServer 4.27.1 / PostgreSQL 14)实测,回显逐行照抄;无法复现的环境相关输出已标注节选。