Pagure 5.14.1 常用 CLI 与运维命令详解

Pagure 5.14.1 常用 CLI 与运维命令详解:pagure-admin 全部子命令实测、gitolite3 与 SSH 授权运维、备份恢复与服务日志取证,所有命令均含真实回显,适用于 Ubuntu 22.04 LTS 环境的日常管理与排障。

Pagure版本控制代码审查DevOps工程2026/10/28

Pagure 5.14.1 常用 CLI 与运维命令详解

目标:系统梳理 Pagure 5.14.1 的运维命令面——管理 CLI pagure-admin 全部 17 个子命令(语法、参数与真实回显)、Web/worker 两个 systemd 单元的服务管理与日志、数据库与 git 仓库的备份恢复、REST API 的令牌调用,以及命令执行身份相关的三类实测故障处置。全部命令与回显已在 Ubuntu 22.04.5 LTS 的 Pagure 5.14.1 实例实测(2026-10-28)。部署与配置见 《Pagure 5.14.1 Ubuntu 22.04 安装指南》 与 《Pagure 5.14.1 配置参数详解》。

一、环境信息

  • 操作系统:Ubuntu 22.04.5 LTS(x86_64)
  • Pagure:5.14.1(源码 /opt/pagure,虚拟环境 /opt/pagure/venv,配置 /etc/pagure/pagure.cfg)
  • PostgreSQL 14.24、Redis 6.0.16、gitolite3 3.6.12-1、Gunicorn 26.2.0、Celery 5.6.3
  • 服务单元:pagure-web、pagure-worker(均 git 用户运行)
  • 日志目录:/var/log/pagure/(access_web.log、error_web.log)
  • 示例管理账号:admin / q1w2e3r4;示例项目 public-demo

二、工具概览

Pagure 的运维命令集中在四个入口:

工具位置用途
pagure-admin/opt/pagure/venv/bin/pagure-admin管理员 CLI:令牌、组、只读、分支、ACL、封禁等
systemd 单元pagure-web / pagure-workerWeb 与异步任务服务的启停和日志
pg_dump + tar系统自带数据库与 git 仓库备份
REST APIhttp://localhost/api/0/脚本化操作(建 issue、查分支等)

pagure-admin --help 全量输出(实测):

usage: pagure-admin [-h] [-c CONFIG] [--debug]
                    {refresh-gitolite,refresh-ssh,clear-hook-token,admin-token,get-watch,update-watch,read-only,new-group,list-groups,block-user,upload-repospanner-hook,ensure-project-hooks,delete-project,sanitize-spam-user,create-branch,set-default-branch,update-acls}
                    ...

The admin CLI for this pagure instance

options:
  -h, --help            show this help message and exit
  -c CONFIG, --config CONFIG
                        Specify a configuration to use
  --debug               Increase the verbosity of the information displayed

actions:
  {refresh-gitolite,refresh-ssh,clear-hook-token,admin-token,get-watch,update-watch,read-only,new-group,list-groups,block-user,upload-repospanner-hook,ensure-project-hooks,delete-project,sanitize-spam-user,create-branch,set-default-branch,update-acls}
    refresh-gitolite    Re-generate the gitolite config file
    refresh-ssh         Re-write to disk every user's ssh key stored in the
                        database
    clear-hook-token    Generate a new hook token for every project in this
                        instance
    admin-token         Manages the admin tokens for this instance
    get-watch           Get someone's watch status on a project
    update-watch        Update someone's watch status on a project
    read-only           Get or set the read-only flag on a project
    new-group           Create a new group on this pagure instance
    list-groups         Lists existing groups on this pagure instance
    block-user          Prevents an user to interact with this pagure instance
                        until the specified date
    upload-repospanner-hook
                        Upload repoSpanner hook script
    ensure-project-hooks
                        Ensure all projects have their hooks setup
    delete-project      Delete the project specified
    sanitize-spam-user  Delete repos and tickets by the user specified
    create-branch       Create the specified branch in the specified project
    set-default-branch  Set the specified branch as default
    update-acls         Update the ACLs stored in the database with the ones
                        defined in the configuration file (addition only, no
                        ACLs are removed from the database).

三、前置条件

  1. PAGURE_ADMIN_USERS 包含执行者用户名(本环境为 ['admin']),否则多数子命令拒绝执行;
  2. 命令需带配置环境:export PAGURE_CONFIG=/etc/pagure/pagure.cfg(或每次前缀该变量);
  3. 涉及 git 仓库直接读写的子命令(create-branch、set-default-branch)应以 git 用户运行,root 会触发 pygit2 属主校验失败(实测报错见 6.4);
  4. 需要操作目标项目存在(本文以 public-demo 为例)。

四、各工具详解

4.1 pagure-admin:API 管理令牌

admin-token 系列管理管理员 API 令牌。先看已有令牌:

PAGURE_CONFIG=/etc/pagure/pagure.cfg /opt/pagure/venv/bin/pagure-admin admin-token list

实测输出:

TC9UXJSDNL9Q5Z99K499N23OTD1XQSVNY2GW5WB1RBRC1XAKOXCXXFL54MQ33WBY -- admin -- 2027-12-31 00:00:00

创建令牌是交互式流程:admin-token create <用户> <到期日> 后先打印 ACL 清单,输入逗号分隔的 ACL 编号,再确认:

printf "0,2,7,10\nn\n" | PAGURE_CONFIG=/etc/pagure/pagure.cfg /opt/pagure/venv/bin/pagure-admin admin-token create admin 2027-06-30

实测输出(回答 n 中止创建,仅演示流程):

0.  internal_access
1.  issue_comment
2.  issue_create
3.  issue_change_status
4.  pull_request_flag
5.  pull_request_comment
6.  pull_request_merge
7.  generate_acls_project
8.  group_modify
9.  commit_flag
10.  create_branch
11.  tag_project
Which ACLs do you want to associated with this token?
(Comma separated list): ACLs selected:
0.  internal_access
2.  issue_create
7.  generate_acls_project
10.  create_branch
Do you want to create this API token?
Do you want to continue? [y/N]

💡 说明:把最后一问回答为 y 即真正创建,令牌明文只显示一次(本环境已创建一枚 2027-12-31 到期的令牌,ACL 为上表 0/2/7/10 四项)。生产环境令牌等同于账号部分权限,按最小授权选择 ACL。

4.2 pagure-admin:用户组管理

创建组(new-group <组名> <创建者用户名>,--display、--description 可选,需确认):

echo y | PAGURE_CONFIG=/etc/pagure/pagure.cfg /opt/pagure/venv/bin/pagure-admin new-group packagers admin --display Packagers --description "Core packager team"

实测输出:

Group `packagers` created.
User `admin` added to the group `packagers`.

列出组:

PAGURE_CONFIG=/etc/pagure/pagure.cfg /opt/pagure/venv/bin/pagure-admin list-groups

实测输出:

List of groups on this Pagure instance:
Group: 1 - name packagers

空实例时该命令返回 No groups found in this pagure instance.(实测)。

4.3 pagure-admin:关注状态(watch)

查询某用户对项目的关注状态(参数顺序为 <项目> <用户>):

PAGURE_CONFIG=/etc/pagure/pagure.cfg /opt/pagure/venv/bin/pagure-admin get-watch public-demo admin

实测输出:

On public-demo user: admin is watching the following items: issues, pull-requests

修改关注状态,合法值为 -1, 0, 1, 2, 3,传错值会实测报错:

PAGURE_CONFIG=/etc/pagure/pagure.cfg /opt/pagure/venv/bin/pagure-admin update-watch public-demo admin --status 1

实测输出:

Updating watch status of admin to 1 (watch issues and PRs) on public-demo
# 反例:--status all
Invalid status provided: all not in -1, 0, 1, 2, 3

4.4 pagure-admin:项目只读开关

不跟值即查询:

PAGURE_CONFIG=/etc/pagure/pagure.cfg /opt/pagure/venv/bin/pagure-admin read-only public-demo

实测输出:

The current read-only flag of the project public-demo is set to False

设置只读/恢复可写(--ro 只接受小写 true/false):

PAGURE_CONFIG=/etc/pagure/pagure.cfg /opt/pagure/venv/bin/pagure-admin read-only public-demo --ro true
PAGURE_CONFIG=/etc/pagure/pagure.cfg /opt/pagure/venv/bin/pagure-admin read-only public-demo --ro false

实测输出(依次两行):

The read-only flag of the project public-demo has been set to True
The read-only flag of the project public-demo has been set to False

💡 说明:只读态下该项目的 git 推送会被拒绝,常用于迁移或事故冻结;恢复可写后无需其他操作。

4.5 pagure-admin:gitolite 与 SSH 维护

重新生成 gitolite ACL 配置并编译(需确认两次):

printf "y\ny\n" | PAGURE_CONFIG=/etc/pagure/pagure.cfg /opt/pagure/venv/bin/pagure-admin refresh-gitolite

实测输出:

Please note that you have not selected a project or --all. Do you want to recompile the existing config file?
Do you want to continue? [y/N]y
Do you want to re-generate the gitolite.conf file for group: None and project: None?
Do you want to continue? [y/N]y
Gitolite ACLs updated

重新落盘全部用户 SSH 公钥(refresh-ssh)在 5.14.1 存在缺陷:直接运行实测报错:

Do you want to re-generate all the ssh keys for every user in the database? (Depending on your instance this may take a while and result in an outage while it lasts)
Do you want to continue? [y/N]y
Error: Working outside of application context.

This typically means that you attempted to use functionality that needed
the current application. To solve this, set up an application context
with app.app_context(). See the documentation for more information.

原因:该子命令调用的 pagure.flask_app.generate_user_key_files() 依赖 Flask 应用上下文与 flask.g.session。等价变通(实测通过,公钥正常生成到 keydir):

PAGURE_CONFIG=/etc/pagure/pagure.cfg /opt/pagure/venv/bin/python -c "
from pagure.flask_app import create_app, generate_user_key_files
import pagure.config
from pagure.lib import model_base
app = create_app()
with app.app_context():
    from flask import g
    g.session = model_base.create_session(pagure.config.config['DB_URL'])
    print(generate_user_key_files())
    g.session.commit()
"

实测输出:

None

💡 说明:函数执行成功无返回值(打印 None),效果等同 refresh-ssh——用户公钥重写进 GITOLITE_KEYDIR。可用 ls /srv/git/gitolite-admin/keydir/ 核对(实测见 admin.pub)。

4.6 pagure-admin:令牌与 ACL 维护

重置全站 hook token(WebHook 密钥,安全事件时用,需确认):

echo y | PAGURE_CONFIG=/etc/pagure/pagure.cfg /opt/pagure/venv/bin/pagure-admin clear-hook-token

实测输出:

Do you want to re-generate all the hook token for every user in the database? This will break every web-hook set-up on this instance. You should only ever run this for a security issue
Do you want to continue? [y/N]y
Hook token all re-generated

同步配置文件中的 ACL 定义到数据库(只增不减,需确认):

echo y | PAGURE_CONFIG=/etc/pagure/pagure.cfg /opt/pagure/venv/bin/pagure-admin update-acls

实测输出:

ACLS in the database synced with the list in the configuration file

4.7 pagure-admin:分支管理

创建分支(以 git 用户运行;--from-branch 与 --from-commit 二选一,末尾两个位置参数是新分支名与操作者):

printf "y\n" | su - git -c "PAGURE_CONFIG=/etc/pagure/pagure.cfg /opt/pagure/venv/bin/pagure-admin create-branch public-demo --from-branch main feature-x admin"

实测输出:

Branch created

用 API 确认:

curl -s http://localhost/api/0/public-demo/git/branches

实测输出:

{"branches":["feature-x","main"],"default":"main","total_branches":2}

设置默认分支(同样以 git 用户运行):

su - git -c "PAGURE_CONFIG=/etc/pagure/pagure.cfg /opt/pagure/venv/bin/pagure-admin set-default-branch public-demo main"

实测输出:

Branch main set as default

⚠️ 注意:create-branch 内部是对仓库的直接 git 推送,会经过 gitolite 的 update 钩子。若报 Can't locate Gitolite/Hooks/Update.pm in @INC,按「七、常见问题」7.2 给钩子补库路径后重试(本环境已修复)。

4.8 pagure-admin:仅 repoSpanner 与高危子命令

  • ensure-project-hooks <hookID>:仅适用于 repoSpanner 存储后端,位置参数是 repoSpanner hook ID;本环境为 gitolite 部署,实测该命令因缺参数报 error: the following arguments are required: hook,未做 repoSpanner 实测。
  • block-user <用户> <日期>、delete-project、sanitize-spam-user:破坏性命令,本环境未实测(避免破坏演示数据)。其行为按命令行定义为:block-user 将用户封禁至指定日期(如 pagure-admin block-user spammer 2027-01-01,预期输出确认提示并写入封禁记录);delete-project 删除指定项目及其仓库;sanitize-spam-user 批量删除指定用户的仓库与工单。三者均需在 PAGURE_ADMIN_USERS 名单内执行并二次确认。

4.9 服务管理与日志

systemctl is-active pagure-web
systemctl is-active pagure-worker
systemctl restart pagure-web
systemctl restart pagure-worker
journalctl -u pagure-worker -n 20 --no-pager

实测输出(is-active 两次各一行):

active
active

Web 访问日志样例(tail /var/log/pagure/access_web.log,实测节选):

 - - [28/Oct/2026:00:41:16 +0000] "GET /api/0/public-demo/git/branches HTTP/1.0" 200 58 "-" "curl/7.81.0"
 - - [28/Oct/2026:00:44:39 +0000] "GET /api/0/public-demo/git/branches HTTP/1.0" 200 70 "-" "curl/7.81.0"

应用错误日志在 /var/log/pagure/error_web.log(Gunicorn error-logfile 落点)。worker 的任务日志(gitolite 编译、邮件发送等)只进 journald,journalctl -u pagure-worker 是排障第一入口(实测案例见 6.1)。

4.10 备份与恢复

数据库备份(含 54 张元数据表)与 git 仓库备份(实测命令):

mkdir -p /srv/backup
su postgres -c "pg_dump pagure" | gzip > /srv/backup/pagure-db-$(date +%F).sql.gz
tar -czf /srv/backup/pagure-git-$(date +%F).tar.gz -C /srv/git repositories gitolite-admin .gitolite.rc
ls -lh /srv/backup/

实测输出:

total 52K
-rw-r--r-- 1 root root 11K Oct 28 00:46 pagure-db.sql.gz
-rw-r--r-- 1 root root 37K Oct 28 00:46 pagure-git.tar.gz

备份完整性校验(实测):

gzip -t /srv/backup/pagure-db.sql.gz && echo DB_DUMP_OK
tar -tzf /srv/backup/pagure-git.tar.gz | head -3

实测输出:

DB_DUMP_OK
repositories/
repositories/gitolite-admin.git/

恢复流程(预期结果,未在实库演练删除后恢复):先 su postgres -c "psql -c 'CREATE DATABASE pagure OWNER pagure;'",再 gunzip -c /srv/backup/pagure-db-<日期>.sql.gz | su postgres -c "psql -d pagure" 导入元数据,最后解包 git 备份回 /srv/git 并 chown -R git:git /srv/git,重启两个服务单元后用 curl -s http://localhost/api/0/version 验证。

4.11 REST API 令牌调用

用 4.1 创建的管理令牌调用 API(Authorization: token <令牌> 头)。实测创建一条工单:

curl -s -X POST "http://localhost/api/0/public-demo/new_issue" \
  -H "Authorization: token TC9UXJSDNL9Q5Z99K499N23OTD1XQSVNY2GW5WB1RBRC1XAKOXCXXFL54MQ33WBY" \
  -H "Content-Type: application/json" \
  -d '{"title":"CLI 实测 issue","issue_content":"Created via REST API with admin token"}'

实测输出(输出节选(实测首尾),完整 JSON 较长):

{"issue":{"assignee":null,"blocks":[],"close_status":null,"closed_at":null,"closed_by":null,"comments":[],"content":"Created via REST API with admin token","custom_fields":[],"date_created":"<bound method Arrow.timestamp of <Arrow [2026-10-28T00:47:17.460093+00:00]>>","depends":[],"full_url":"http:/

匿名可读的分支查询无需令牌(实测):

curl -s http://localhost/api/0/public-demo/git/branches
{"branches":["feature-x","main"],"default":"main","total_branches":2}

4.12 gitolite 常用命令

手工触发 gitolite 编译(等效 refresh-gitolite 的编译段,以 git 用户执行):

su - git -c "HOME=/srv/git gitolite compile && echo COMPILE_OK"

实测输出:

COMPILE_OK

SSH 通道与授权自检(列出当前账号被授权的全部仓库):

ssh -i ~/.ssh/pagure_admin git@localhost info

实测输出:

hello admin, this is git@pagure running gitolite3 3.6.12-1 (Debian) on git 2.34.1

 R W	admin/demo-project
 R W	docs/admin/demo-project
 R W	docs/public-demo
 R W	public-demo
 R W	requests/admin/demo-project
 R W	requests/public-demo
 R W	tickets/admin/demo-project
 R W	tickets/public-demo

五、注意事项

  1. 执行身份:会触发 gitolite 编译的命令(refresh-gitolite)与直写 git 仓库的命令(create-branch、set-default-branch)以 git 用户运行最安全;root 运行会把 authorized_keys、仓库文件写成 root 属主,引发后续 worker 报错(见 6.1)。
  2. 交互确认:refresh-gitolite 要确认两次、refresh-ssh/clear-hook-token/update-acls/create-branch 各一次;脚本化时用 printf "y\ny\n" | 管道应答。
  3. 令牌安全:admin-token create 的令牌明文仅显示一次;clear-hook-token 会打断全部 WebHook。
  4. --ro 与 watch 状态值大小写敏感:--ro 只认小写 true/false,watch 只认 -1,0,1,2,3。
  5. get-watch/update-watch 参数顺序是 <项目> <用户>,与直觉相反,写反会报 No user "<项目名>" found(实测)。

六、常用命令速查

日常运维按「高频 → 低频」排序的命令速查表(执行身份栏 P=root 可执行、G=建议 git 用户):

目的命令(PA=/opt/pagure/venv/bin/pagure-admin)身份
查服务状态systemctl is-active pagure-web / is-active pagure-workerP
看 worker 日志journalctl -u pagure-worker -n 20 --no-pagerP
列管理员令牌PA admin-token listP
创建组PA new-group <组> <用户> --display <显示名>P
列组PA list-groupsP
查关注状态PA get-watch <项目> <用户>P
项目只读PA read-only <项目> [--ro true|false]P
重建 gitolite ACLPA refresh-gitolite(两次确认)G
重写用户公钥4.5 节 app_context 变通命令P
重置 hook tokenPA clear-hook-token(打断全部 WebHook)P
同步 ACL 定义PA update-aclsP
建分支PA create-branch <项目> --from-branch <源> <新分支> <操作者>G
设默认分支PA set-default-branch <项目> <分支>G
数据库备份su postgres -c "pg_dump pagure" | gzip > <文件>P
仓库备份tar -czf <文件> -C /srv/git repositories gitolite-admin .gitolite.rcP
SSH 授权自检ssh -i ~/.ssh/pagure_admin git@localhost infoP
手工编译 gitolitesu - git -c "HOME=/srv/git gitolite compile"G

速查表解读:日常巡检用前两行加 API 探活(curl -s http://localhost/api/0/version);变更类操作集中在 gitolite/分支三行,务必按身份栏执行;备份两行建议纳入 cron,文件名带日期(4.10 节实测形态)。

七、常见问题

7.1 worker 报 authorized_keys Permission denied

现象:journalctl -u pagure-worker 实测出现:

Oct 28 00:46:12 pagure celery[8032]:     raise pagure.exceptions.PagureException(error_msg)
Oct 28 00:46:12 pagure celery[8032]: pagure.exceptions.PagureException: The command "HOME=/srv/git gitolite compile && HOME=/srv/git gitolite trigger POST_COMPILE" failed with
Oct 28 00:46:12 pagure celery[8032]:   out: "b''
Oct 28 00:46:12 pagure celery[8032]:   err:"b'FATAL: open /srv/git/.ssh/authorized_keys failed: Permission denied\n\n'"

定位与解决:stat -c '%U:%G %a' /srv/git/.ssh/authorized_keys 发现属主是 root(此前以 root 跑过 refresh-gitolite)。修复:

chown git:git /srv/git/.ssh/authorized_keys
chmod 600 /srv/git/.ssh/authorized_keys
su - git -c "HOME=/srv/git gitolite compile && echo COMPILE_OK"

实测输出:

COMPILE_OK

7.2 create-branch 报 Can't locate Gitolite/Hooks/Update.pm

现象:pagure-admin create-branch 以 root 执行时实测报:

Empty compile time value given to use lib at hooks/update line 6.
Can't locate Gitolite/Hooks/Update.pm in @INC (you may need to install the Gitolite::Hooks::Update module) ...
error: hook declined to update refs/heads/feature-x

原因:gitolite 的 update 钩子依赖环境变量 GL_LIBDIR(仅经 gitolite-shell 网关的 SSH 推送才会注入);create-branch 内部直推仓库绕过了网关,use lib $ENV{GL_LIBDIR} 拿到空值。 解决:给钩子加 Debian 库路径兜底(实测后 create-branch 返回 Branch created):

sed -i "s|use lib \$ENV{GL_LIBDIR};|use lib \$ENV{GL_LIBDIR} \|\| '/usr/share/gitolite3/lib';|" \
  /srv/git/gitolite-admin/hooks/common/update

7.3 refresh-ssh 报 Working outside of application context

现象与等价变通见 4.5 节:5.14.1 的 pagure-admin refresh-ssh 缺应用上下文支撑,用 create_app().app_context() 包装 generate_user_key_files() 实测可完成同等操作。

7.4 以 root 运行仓库类子命令报属主错误

现象(实测):

_pygit2.GitError: /srv/git/repositories/public-demo.git: repository path '/srv/git/repositories/public-demo.git/' is not owned by current user

解决:切 git 用户执行(su - git -c "PAGURE_CONFIG=/etc/pagure/pagure.cfg /opt/pagure/venv/bin/pagure-admin ..."),仅数据库类子命令(admin-token、list-groups 等)不受此限制。

7.5 SSH 推送报 pre-receive hook declined

现象:git push 报 remote: /usr/bin/env: 'python': No such file or directory 与 ! [remote rejected] main -> main (pre-receive hook declined)。 原因与解决:Pagure 仓库钩子 hookrunner 的 shebang 是 #!/usr/bin/env python,虚拟环境无该名字的解释器;把 shebang 改为虚拟环境绝对路径即可(完整排障过程与修复后实测输出见《Pagure 5.14.1 Ubuntu 22.04 安装指南》8.3 节)。

七、参考链接