Claper 3.2.0 常用 CLI 命令与工具详解

Claper 3.2.0 服务器运维命令面全解:发布包入口 bin/claper 的 11 个子命令逐一实测(eval/rpc/remote/version/pid)、管理员改密与空壳事件处置实录、SECRET_KEY_BASE 注入与轮换双向会话失效验证、PostgreSQL 42 表备份恢复演练、日志排查路径与 /events 500 KeyError 排障实录。

ClaperClaperElixirPostgreSQL2026/11/01

Claper 3.2.0 常用 CLI 命令与工具详解

目标:系统讲清 Claper 3.2.0 在服务器上的运维命令面——发布包入口 bin/claper 的 11 个子命令逐一实测(eval / rpc / remote / version / pid 等)、管理员口令与演示事件的服务器端处置、SECRET_KEY_BASE 环境变量注入与轮换验证、PostgreSQL 演示事件数据备份恢复演练、日志排查路径与一则 /events 500 崩溃排障实录。全部输入输出为 Ubuntu 22.04 运维主机实测(2026-11-01)。部署过程见 《Claper Docker Compose 部署指南》,参数含义见 《Claper 3.2.0 配置参数详解》,产品背景见 《Claper 介绍与选型指南》。

一、环境信息

本文按 systemd 托管的服务器形态叙述:

项目值
操作系统Ubuntu 22.04(x86_64)
Claper 版本3.2.0(version 子命令实测回显 claper 3.2.0)
运行时Erlang/OTP 28(erts-16.0.1)、Elixir 1.18.4、cowboy 2.19.0、phoenix_live_view 1.0.19(均取自实测回显)
发布包安装目录/opt/claper,命令入口 /opt/claper/bin/claper
环境变量文件/opt/claper/.env(BASE_URL、DATABASE_URL、SECRET_KEY_BASE 等,含义见 C1 篇)
服务单元claper.service(启动序列先执行 eval 'Claper.Release.migrate(); Claper.Release.seeds()' 再 start,为官方发布包的既定启动方式)
演示文件存储目录/opt/claper/uploads(PRESENTATION_STORAGE_DIR)
数据库PostgreSQL 15.19,本机 5432,库/用户均为 claper
对外访问http://localhost:8129(BASE_URL)
示例管理账号admin@claper.co / q1w2e3r4(官方种子账号 admin@claper.co/claper 部署后已改密)

二、工具概览

Claper 是 Elixir/Phoenix 发布包(release),全部服务器端运维能力集中在一个入口 /opt/claper/bin/claper,用法帮助以传入未知子命令触发(实测回显逐行照抄):

/opt/claper/bin/claper badcommand
Usage: claper COMMAND [ARGS]

The known commands are:

    start          Starts the system
    start_iex      Starts the system with IEx attached
    daemon         Starts the system as a daemon
    daemon_iex     Starts the system as a daemon with IEx attached
    eval "EXPR"    Executes the given expression on a new, non-booted system
    rpc "EXPR"     Executes the given expression remotely on the running system
    remote         Connects to the running system via a remote shell
    restart        Restarts the running system via a remote command
    stop           Stops the running system via a remote command
    pid            Prints the operating system PID of the running system via a remote command
    version        Prints the release name and version to be booted

ERROR: Unknown command badcommand

按运维频率分档:

档位子命令用途
日常必用version、pid、eval、rpc状态核对;冷执行(生成密钥、跑迁移);热执行(查改运行数据)
深入排查remote连入运行节点的交互式控制台(IEx)
服务控制start、start_iex、daemon、daemon_iex、restart、stop由服务管理器接管,日常勿手执(见 5.5 与注意事项)

与常见预期的三处差异(均为实测,防按其他 Phoenix 应用的惯例踩空):

  1. 没有 migrate 子命令。执行 /opt/claper/bin/claper migrate 实测回显 ERROR: Unknown command migrate。迁移走 eval 'Claper.Release.migrate()'(见 5.2)。
  2. 没有 phx.gen.secret 子命令。实测同样 ERROR: Unknown command phx.gen.secret。生成密钥用 eval 加 Erlang 随机数,或服务器上的 openssl rand -base64 48(见 5.2、第六章)。
  3. 交互式控制台的子命令名是 remote,不是 remote_console(后者实测 ERROR: Unknown command remote_console)。

数据平面上还有两组工具配合使用:rpc/remote 里可直接调用应用上下文模块(Claper.Events、Claper.Accounts 等)做业务级查改;数据库层用 pg_dump/psql 做演示事件数据的备份恢复(第七章)。

三、前置条件

  1. 服务在跑。/opt/claper/bin/claper pid 有回显即运行中;rpc/remote/stop 等远程类子命令都要求节点已启动。
  2. 运维账号对 /opt/claper 有执行权限(root 或服务账号均可)。
  3. remote 需要交互式终端(有 TTY 的 SSH 会话),非交互管道会失败,见 5.4 实测。
  4. 数据库运维需 psql/pg_dump 客户端与凭据:
export PGHOST=127.0.0.1 PGUSER=claper PGPASSWORD=claper PGDATABASE=claper
  1. 改密、删事件等写操作前,先确认对应业务影响(口令变更会踢掉该用户全部会话,见 5.3)。

四、服务状态核对命令

4.1 version:核对发布版本

/opt/claper/bin/claper version
claper 3.2.0

注意 version 打印的是发布包将启动的版本,与服务当前是否运行无关,适合升级后核对。

4.2 pid:取运行进程号

/opt/claper/bin/claper pid
310

回显为运行节点的操作系统 PID。配合 top -p 310、cat /proc/310/status 可做资源核对;pid 无回显即服务未运行。

4.3 rpc 探活:确认节点真正可服务

/opt/claper/bin/claper rpc 'IO.inspect({:os.getpid() |> List.to_integer(), Application.get_env(:claper, ClaperWeb.Endpoint)[:url][:host]}, label: "info")'
info: {310, "localhost"}

返回 PID 与端点配置,与 4.2 的 pid 相互印证。

五、各命令详解

5.1 eval:冷执行(不起服务的临时系统)

eval "EXPR" 会新起一个未启动的临时系统执行表达式后退出,不与运行节点交互。最小示例:

/opt/claper/bin/claper eval 'IO.puts("eval-ok")'
eval-ok

两个高频运维用途:

(1)生成 SECRET_KEY_BASE(替代不可用的 phx.gen.secret,实测回显为 64 字符 base64):

/opt/claper/bin/claper eval 'IO.puts(:crypto.strong_rand_bytes(48) |> Base.encode64())'
7uxTF9Nr53NY/u50SHOnqKvmwexBtfAaVP58pMUDzfouRfoD8BN1olicnOIf36vW

(此值仅为演示生成、未投入使用;生产生成后直接写入 .env,不要粘贴到聊天/工单。)

(2)手动执行数据库迁移(Claper 3.2.0 的 migrate 命令不存在,官方启动序列即走此表达式):

/opt/claper/bin/claper eval 'Claper.Release.migrate()'
11:53:09.786 [info] Migrations already up

升级发布包后、切换启动新版本前执行一次,回显 Migrations already up 表示 schema 已就位;该表达式幂等,可安全重复执行。

5.2 rpc:热执行(连入运行节点)

rpc "EXPR" 在运行中的节点上执行表达式,能直接访问应用状态(Repo、上下文模块、运行时配置)。

第一个实测坑:rpc 不会自动打印表达式返回值。

/opt/claper/bin/claper rpc 'Node.list()'
(无任何输出,退出码 0)

表达式返回值被丢弃,必须自带 IO.puts/IO.inspect。修正写法与常用查询实测:

统计演示事件数:

/opt/claper/bin/claper rpc 'IO.inspect(Claper.Repo.query!("select count(*) from events").rows, label: "events_count")'
events_count: [[2]]

读取运行时全局配置表 global_configs(Web 界面「实例设置」的落库处,见 C1 篇第三章):

/opt/claper/bin/claper rpc 'IO.inspect(Claper.Repo.query!("select key, value from global_configs order by key").rows, limit: :infinity)'
[
  ["lti_enabled", "false"],
  ["transcription_api_key", nil],
  ["transcription_default_language", nil],
  ["transcription_enabled", "false"]
]

5.3 rpc 实录:服务器端修改管理员口令

Web 界面不可用(忘记密码、批量建号)时的服务器端处置。用 Claper.Accounts.update_user_password/3,第一个参数是当前口令做校验:

/opt/claper/bin/claper rpc 'u = Claper.Accounts.get_user_by_email("admin@claper.co"); IO.inspect(Claper.Accounts.update_user_password(u, "q1w2e3r4", %{"password" => "S8rotate!", "password_confirmation" => "S8rotate!"}))'

实测回显(成功返回 {:ok, 用户结构体},节选):

{:ok,
 #Claper.Accounts.User<
   __meta__: #Ecto.Schema.Metadata<:loaded, "users">,
   id: 1,
   uuid: "fef7588f-708b-4321-8088-fda412f4cd42",
   email: "admin@claper.co",
   first_name: "Claper",
   last_name: "Admin",
   is_randomized_password: false,
   confirmed_at: ~N[2026-11-01 10:30:33],
   locale: nil,
   deleted_at: nil,
   ...
   updated_at: ~N[2026-11-01 11:54:10],
 >}

curl 走登录接口验证新口令生效(Phoenix 表单参数须为 user[email] 嵌套形式,取 CSRF 令牌的方式见 B2 篇 4.6):

CSRF=$(curl -s -c jar.txt http://localhost:8129/users/log_in \
  | grep -oE '<input name="_csrf_token"[^>]*value="[^"]+"' | grep -oE 'value="[^"]+"' | head -1 | cut -d'"' -f2)
curl -s -b jar.txt -c jar.txt -o /dev/null -w "LOGIN_NEWPW=%{http_code} REDIRECT=%{redirect_url}\n" \
  -X POST http://localhost:8129/users/log_in \
  --data-urlencode "user[email]=admin@claper.co" \
  --data-urlencode "user[password]=S8rotate!" \
  --data-urlencode "user[remember]=true" \
  --data-urlencode "_csrf_token=$CSRF"
LOGIN_NEWPW=302 REDIRECT=http://localhost:8129/events

⚠️ 该函数会连带删除该用户全部 users_tokens(源码中 Ecto.Multi.delete_all(:tokens, ...)),即所有旧会话、记住登录、重置密码链接一次性作废,用户须重新登录。演示进行中切勿对演讲者账号执行。

验证后回滚到基准口令(同法,实测 LOGIN_REVERT=302 REDIRECT=http://localhost:8129/events、后续页面 EVENTS=200):

/opt/claper/bin/claper rpc 'u = Claper.Accounts.get_user_by_email("admin@claper.co"); IO.inspect(Claper.Accounts.update_user_password(u, "S8rotate!", %{"password" => "q1w2e3r4", "password_confirmation" => "q1w2e3r4"}))'
{:ok,
 #Claper.Accounts.User<
   __meta__: #Ecto.Schema.Metadata<:loaded, "users">,
   id: 1,
   uuid: "fef7588f-708b-4321-8088-fda412f4cd42",
   email: "admin@claper.co",
   ...
 >}

5.4 remote:远程交互式控制台(IEx)

连入运行节点获得完整 Elixir 交互环境,适合逐步试探、查长结构体。

先实测一个坑:remote 需要 TTY。在非交互管道里执行(如 cron、CI 步骤)回显:

Erlang/OTP 28 [erts-16.0.1] [source] [64-bit] [smp:128:6] [ds:128:6:10] [async-threads:1] [jit:ns]

*** ERROR: Shell process terminated! (^G to start new job) ***

节点 banner 出现说明已连上,但 shell 因无终端立即终止——结论:remote 只能在交互式 SSH 会话里用;脚本化需求一律改用 rpc。

交互会话实测记录(登录后逐行键入):

Erlang/OTP 28 [erts-16.0.1] [source] [64-bit] [smp:128:6] [ds:128:6:10] [async-threads:1] [jit:ns]

Interactive Elixir (1.18.4) - press Ctrl+C to exit (type h() ENTER for help)
iex(claper@60a8a7a8937a)1> IO.puts("remote-console-ok")
remote-console-ok
:ok
iex(claper@60a8a7a8937a)2>

提示符 iex(claper@节点名) 中的节点名即运行主机名。控制台内可直接调用 5.2 的全部表达式且返回值自动打印。

退出方式:按 Ctrl+C 进入中断菜单(实测回显):

BREAK: (a)bort (A)bort with dump (c)ontinue (p)roc info (i)nfo
       (l)oaded (v)ersion (k)ill (D)b-tables (d)istribution

按 a(abort)退出——只终止本地 shell 进程,不影响运行节点。切勿在控制台里执行 System.halt() 或 :init.stop(),那会停掉生产节点本身。

5.5 start / restart / stop:服务控制命令

start、daemon 用于前台/后台拉起系统,restart、stop 向运行节点发送远程停机指令。在 systemd 托管形态下日常不要手执这几条:服务主进程就是 start 拉起的节点,stop 会让主进程退出、单元随之进入停止态,restart 同理绕过服务管理器的重启策略与依赖顺序。服务重启统一用:

systemctl restart claper

本文取证环境全程在跑,stop/restart 未实测执行(执行即中断服务),仅给出结论性警告;pid 无回显 + systemctl status claper 是判断服务状态的正规路径。

六、环境变量注入运维与 SECRET_KEY_BASE 轮换

Claper 的全部运行参数经环境变量注入(三层配置体系见 《Claper 3.2.0 配置参数详解》)。运维要点:改 /opt/claper/.env 后必须 systemctl restart claper 才生效——eval/rpc 读到的都是进程已加载的值,改文件不影响运行中的进程。

注入生效的实测验证:为验证轮换影响,在同机以不同环境变量并行起了一个临时实例(端口 8139、数据库指向第七章的恢复库 claper_restore、注入新生成的 SECRET_KEY_BASE),与主实例(SECRET_KEY_BASE 前缀 xvAqu9LW)形成对照:

openssl rand -base64 48 | tee /dev/stderr | wc -c
M8KhDQ8w…(64 字符 base64,全文已省略)
LEN=64

(生成值仅注入临时实例、用后即毁;生产密钥同样不得外传。)

临时实例启动日志(逐行照抄,可见注入的 BASE_URL 生效):

11:57:06.990 [info] Migrations already up
Global settings seeded
11:57:08.300 [info] Running ClaperWeb.Endpoint with cowboy 2.19.0 at 0.0.0.0:4000 (http)
11:57:08.304 [info] Access ClaperWeb.Endpoint at http://localhost:8139

用 eval 读取两个实例已加载的密钥前缀核对注入结果:

/opt/claper/bin/claper eval 'IO.puts("loaded=" <> String.slice(Application.get_env(:claper, ClaperWeb.Endpoint)[:secret_key_base], 0, 8))'
loaded=xvAqu9LW

临时实例上同法执行回显 loaded=M8KhDQ8w——与注入值前缀一致,证明环境变量注入链路(.env → 进程启动 → 端点配置)成立。

轮换的会话影响(实测):会话 cookie 由 SECRET_KEY_BASE 签名,轮换后新旧密钥互不认账,双向验证:

# 主实例(旧密钥)签发的 cookie,访问新密钥实例:
curl -s -b jar.txt -o /dev/null -w "OLDCOOKIE_ON_ROT=%{http_code} REDIRECT=%{redirect_url}\n" http://localhost:8139/events
# 新密钥实例签发的 cookie,访问主实例:
curl -s -b jar4.txt -o /dev/null -w "ROTCOOKIE_ON_MAIN=%{http_code} REDIRECT=%{redirect_url}\n" http://localhost:8129/events
OLDCOOKIE_ON_ROT=302 REDIRECT=http://localhost:8139/users/log_in
ROTCOOKIE_ON_MAIN=302 REDIRECT=http://localhost:8129/users/log_in

两条 302 都跳回登录页:轮换即全员下线,正在演示的演讲者/观众会话全部失效。标准轮换流程:

  1. 选演示空档;
  2. eval 或 openssl rand -base64 48 生成新密钥,更新 /opt/claper/.env 的 SECRET_KEY_BASE;
  3. systemctl restart claper;
  4. curl -s -o /dev/null -w "%{http_code}\n" http://localhost:8129/ 验证返回 200,重新登录确认。

官方 README 特别警告:SECRET_KEY_BASE 泄露或沿用示例值,他人可伪造 user_id=1 的 admin 会话 cookie 直接接管实例(见 B2 篇第三章),泄露后必须立即轮换。

七、数据库运维:演示事件数据备份与恢复

Claper 的业务数据(事件、演示文件元数据、投票、问答、弹幕、用户)全部在 PostgreSQL claper 库,实测共 42 张表;演示文稿本体文件在 /opt/claper/uploads,备份必须库+目录成对做。

7.1 pg_dump 备份

pg_dump -h 127.0.0.1 -U claper claper > claper-backup-20261101.sql
ls -l claper-backup-20261101.sql
-rw-r--r-- 1 root root 110256 Nov  1 19:53 claper-backup-20261101.sql

备份文件头部(逐行照抄)确认来源版本与依赖扩展:

-- Dumped from database version 15.19 (Debian 15.19-1.pgdg13+2)
-- Dumped by pg_dump version 15.19 (Debian 15.19-1.pgdg13+2)
...
CREATE EXTENSION IF NOT EXISTS citext WITH SCHEMA public;

citext 扩展(大小写不敏感邮箱列)会随 dump 重建,目标库须允许该扩展。

7.2 恢复到新库验证

psql -h 127.0.0.1 -U claper -d postgres -c "CREATE DATABASE claper_restore OWNER claper"
psql -h 127.0.0.1 -U claper -d claper_restore -q < claper-backup-20261101.sql
CREATE DATABASE

恢复全程无报错(stderr 空文件),序列值重置输出(setval 若干行)正常。验证表结构与数据:

psql -h 127.0.0.1 -U claper -d claper_restore -c '\dt' -c 'select id, name, code from events order by id'
(42 rows)

 id |     name     |  code
----+--------------+--------
  1 | Demo Event   | demo01
  2 | 中文事件测试 | zhtest
(2 rows)

42 张表全量重建,事件数据(含中文事件名)逐行还原——这也是 C1 篇中文编码修复后的回归验证。核心表速览(\dt 实测节选):events(演示事件)、presentation_files/presentation_states(演示文件与播放状态)、polls/poll_ballots/poll_votes(投票)、posts/reactions(弹幕与反应)、quiz_questions/quiz_responses(测验)、form_submits(表单)、users/users_tokens/roles(账号)、global_configs(实例设置)、oban_jobs(后台任务)、audit_logs(审计)。

7.3 表名坑:没有 presentations 表

按直觉查演示文件会踩空(实测):

psql -h 127.0.0.1 -U claper -d claper -c "select count(*) from presentations"
ERROR:  relation "presentations" does not exist
LINE 1: select count(*) from presentations
                             ^

真实表名是 presentation_files(文件元数据,含 status、slide_order)与 presentation_states(播放状态)。写巡检 SQL 前先 \dt 确认。

7.4 备份策略建议

  • 每日 pg_dump + /opt/claper/uploads 目录 rsync,两者时间窗对齐(库里的文件哈希指向 uploads 里的实体);
  • 恢复演练按月做一次,像 7.2 一样恢复到旁库验证行数,勿在生产库直接灌 dump;
  • 事件删除是级联的(events → presentation_files → polls/posts 等同删),恢复旁库后如需清理测试数据,优先走 5.4 控制台或 rpc 的应用层函数,让应用同步清理 uploads 实体文件。

八、日志排查路径

服务日志走标准输出,由 journald 收集:

journalctl -u claper -f            # 实时跟踪
journalctl -u claper --since "10 min ago" | grep -v oban   # 过滤后台任务噪音

8.1 启动基线

一次正常启动的标志性四行(实测照抄):

11:31:56.521 [info] Migrations already up
Global settings seeded
11:31:57.720 [info] Running ClaperWeb.Endpoint with cowboy 2.19.0 at 0.0.0.0:4000 (http)
11:31:57.723 [info] Access ClaperWeb.Endpoint at http://localhost:8129

缺行定位:无 Migrations already up → 数据库连接/迁移问题(查 DATABASE_URL);有迁移无 Running ... Endpoint → 端口或配置校验失败(对照 C1 篇启动校验规则);Access ... at 后的地址即 BASE_URL 注入结果,观众链接不对先查这行。

8.2 常态噪音(勿当故障)

  • 健康探测:GET / + Sent 200 in 501µs 每 30 秒一对,来自服务可用性探测(curl --fail http://localhost:4000);
  • Oban 任务插件:{"source":"oban","event":"plugin:stop",...} JSON 行每 30 秒一组,为后台任务队列心跳;
  • OIDC 周期报错(实测每 60 秒):
[error] GenServer Claper.OidcProviderConfig terminating
** (stop) {:configuration_load_failed, :timeout}
Last message: {:continue, :load_configuration}

未配置 OIDC 单点登录时该进程加载配置超时重启,属已知无害噪音,不影响登录与演示功能;若嫌干扰日志检索,grep -v OidcProviderConfig 过滤即可。

8.3 请求定位

每个请求带 request_id,日志两行成对:

11:54:18.544 request_id=GOPpuUQf7vbfqkIAAhoB [info] GET /events
11:54:18.551 request_id=GOPpuUQf7vbfqkIAAhoB [info] Sent 500 in 6ms

用户反馈页面异常时,让其提供页面源码/响应头里的 request_id,journalctl -u claper | grep GOPpuUQf 直接捞出全链路。

8.4 排障实录:/events 列表页 500(KeyError :status)

现象:管理员登录成功(LOGIN=302 REDIRECT=http://localhost:8129/events),但事件列表页返回 500:

11:54:18.551 request_id=GOPpuUQf7vbfqkIAAhoB [info] Sent 500 in 6ms
11:54:18.551 [error] #PID<0.3271.0> running ClaperWeb.Endpoint (connection #PID<0.3270.0>, stream id 1) terminated
Server: localhost:8129 (http)
Request: GET /events
** (exit) an exception was raised:
    ** (KeyError) key :status not found in: nil

If you are using the dot syntax, such as map.field, make sure the left-hand side of the dot is a map
        (claper 3.2.0) lib/claper_web/live/event_live/event_card_component.ex:577: anonymous fn/2 in ClaperWeb.EventLive.EventCardComponent.render_mobile_card/1
        (phoenix_live_view 1.0.19) lib/phoenix_live_view/diff.ex:414: Phoenix.LiveView.Diff.traverse/7

定位:栈顶直指 event_card_component.ex:577 的 render_mobile_card——渲染事件卡片时读演示文件的 status 字段,而该值为 nil。回库核对:

psql -h 127.0.0.1 -U claper -d claper -c "select id, event_id, status, length from presentation_files"
 id | event_id | status | length
----+----------+--------+--------
  1 |        1 | ready  |      1
(1 row)

events 表有 2 个事件,presentation_files 只有事件 1 的记录——事件 2 是只建了壳、从未上传演示文稿的事件。结论:Claper 3.2.0 的事件列表组件未对「无演示文件的事件」判空,这类事件存在时整个列表页崩溃(移动端卡片分支 render_mobile_card 直接取 status)。

复现:用第七章的恢复库 + 新实例(8139)访问 /events,同一栈顶逐行一致:

** (KeyError) key :status not found in: nil
        (claper 3.2.0) lib/claper_web/live/event_live/event_card_component.ex:577: anonymous fn/2 in ClaperWeb.EventLive.EventCardComponent.render_mobile_card/1

证明是数据驱动的确定性缺陷,非环境偶发。

处置:给该事件补传演示文稿,或删除空壳事件。删除走 rpc 应用层函数(同步清理关联数据与存储文件,实测回显节选,inspect 对非 ASCII 名按 \x{XXXX} 转义显示):

/opt/claper/bin/claper rpc 'IO.inspect(Claper.Events.delete_event(Claper.Events.get_event!(2)))'
{:ok,
 %Claper.Events.Event{
   __meta__: #Ecto.Schema.Metadata<:deleted, "events">,
   id: 2,
   uuid: "81ff5430-5bcf-483c-932f-039b99fe5df7",
   name: "\x{4E2D}\x{6587}\x{4E8B}\x{4EF6}\x{6D4B}\x{8BD5}",
   code: "zhtest",
   presentation_file: nil,
   ...
 >}

回显中 presentation_file: nil 与前述诊断互相印证。删除后列表页恢复:

EVENTS=200

九、注意事项

  1. eval 与 rpc 别混用:eval 冷起临时系统,读不到运行中状态、也不影响运行节点,适合密钥生成与迁移;rpc 依赖服务在跑,适合查改业务数据。服务停着时 rpc 会失败,先 systemctl start claper。
  2. rpc 返回值不打印,表达式必须自带 IO.puts/IO.inspect(5.2 实测),否则「命令成功但毫无输出」极易误判为失败。
  3. remote 只走交互式终端;脚本一律 rpc。控制台退出用 Ctrl+C → a,禁用 System.halt()。
  4. stop/restart 子命令与服务管理器冲突,重启统一 systemctl restart claper。
  5. 改密即踢会话:update_user_password 连带清空用户全部令牌(5.3),演示进行中禁止对演讲者账号执行。
  6. SECRET_KEY_BASE 轮换=全员下线(6 章双向 302 实测),且旧密钥泄露视同 admin 权限泄露,须立即轮换。
  7. 密钥值不落日志、不进工单;核对注入是否生效用前缀比对(String.slice(0, 8))即可。
  8. 备份成对:数据库 dump + /opt/claper/uploads 目录,缺一即无法完整恢复演示。
  9. 中文运维:进程环境须带 ELIXIR_ERL_OPTIONS=+fnu(C1 篇第二章),否则文件名/事件名含非 ASCII 时字符串处理报错;IO.inspect 默认把中文转义为 \x{4E2D} 形态属显示行为,非数据损坏。

十、常见问题

症状原因处置
ERROR: Unknown command migrate / phx.gen.secret / remote_consoleClaper 3.2.0 发布包未收录这些子命令(第二章实测)分别用 eval 'Claper.Release.migrate()'、eval 随机数或 openssl rand -base64 48、remote
rpc 执行后没有任何输出但退出码 0rpc 不打印返回值表达式包 IO.inspect/IO.puts
remote 报 *** ERROR: Shell process terminated!无 TTY(管道/cron 环境)换交互式 SSH,或改用 rpc
登录后 /events 返回 500,日志 KeyError :status ... event_card_component.ex:577存在未上传演示文稿的事件,列表卡片组件未判空(8.4 实录)补传演示文稿或 rpc 删除空壳事件
日志每 60 秒刷 OidcProviderConfig terminating {:configuration_load_failed, :timeout}未配置 OIDC 时的周期加载噪音(8.2)无害,grep -v 过滤
select ... from presentations 报表不存在表名实为 presentation_files/presentation_states(7.3)先 \dt 核对表名
轮换 SECRET_KEY_BASE 后所有人都被踢回登录页会话签名密钥变更,属预期安全行为(第六章)按空档轮换流程执行
eval 'Claper.Release.migrate()' 报连接错误DATABASE_URL 不可达或库不存在核对 .env 后 systemctl restart claper,再查数据库服务

十一、参考链接

Claper 3.2.0 常用 CLI 命令与工具详解 - Quzuo