LimeSurvey 常用命令与运维实战
LimeSurvey 7.7 常用命令与运维实战:console.php 十八命令实测(install/updatedb/resetpassword/checkintegrity)、RemoteControl API 全链路(会话认证/激活/令牌/答卷/导出)、备份恢复演练与巡检速查,含会话过期等排障实录。
LimeSurvey 常用命令与运维实战
版本基线:LimeSurvey Community Edition 7.7.0(
martialblog/limesurvey:7.7.0-261020-apache),实例经 《LimeSurvey 7.7 Docker Compose 部署实战》 完成部署安装 实测环境:应用根目录/var/www/html,管理员账号admin,示例问卷 ID62831(问卷名 Builder Smoke Test,含单选 L + 短文本 S + 数值 5 三题) 读者前置:已完成部署安装与基本配置(配置体系见 《LimeSurvey 配置参数详解》)
一、运维三支柱总览
LimeSurvey 的日常运维围绕三条主线展开:
| 支柱 | 入口 | 典型任务 |
|---|---|---|
| 命令行 | application/commands/console.php(应用根目录) | 安装/升级/改密/数据完整性检查/问卷导入 |
| RemoteControl API | POST /index.php/admin/remotecontrol(JSON-RPC 风格) | 问卷全生命周期管理:导入/激活/令牌/答卷/导出 |
| 备份恢复 | 数据库 dump + 应用目录关键文件 | 例行备份、迁移、回退 |
命令行入口说明:所有 console.php 命令在应用根目录下执行。Docker 部署形态的执行方式(exec 进入应用)与数据卷位置见部署篇;裸机 tar.gz 部署则直接 cd <应用根目录> 后执行,命令本体一致。
二、console.php 命令行
2.1 命令清单(实测)
无参数执行 php application/commands/console.php 即列出全部命令,7.7.0 实测回显(18 个):
- install
- updatedb
- importsurvey
- resetpassword
- checkintegrity
- wipe
- plugin
- message
- migrate
- serve
- shell
- uninstall
- ...
清单中混有 Yii 框架自带命令(migrate/serve/shell 等来自底层 framework,LimeSurvey 自己的主要是前八个)。每个命令支持 help <命令名> 查看用法。
2.2 install:静默安装
php application/commands/console.php install <用户名> <密码> <姓名> <邮箱>
数据库连接信息来自 application/config/config.php,执行后初始化全部数据表并创建指定管理员。要求数据库为空库(已有数据时以 updatedb 处理)。Docker 镜像的 entrypoint 正是用该命令实现首启自动安装(部署篇 4.2 节实测日志:Admin user admin created with email admin@example.com)。
2.3 updatedb:数据库结构升级
$ php application/commands/console.php updatedb
no need update : DB is up-to-date
执行数据库结构到当前应用版本的迁移。升级镜像/替换程序包后必须跑一次(Docker 形态由 entrypoint 首启自动执行,日志可见 DB is up-to-date)。数据库结构版本与应用版本不匹配时,后台也会红条提醒。
2.4 resetpassword:命令行改管理员密码
$ php application/commands/console.php resetpassword admin NewPass123
Password for user admin was set.
$ php application/commands/console.php resetpassword admin q1w2e3r4
Password for user admin was set.
忘记管理员密码的标准自救路径(改完记得改回)。实测 exit code 0。也可以直接后台「用户管理」改密,但后台入口丢失时(SSO 故障/密码策略锁死)命令行是最后手段。
2.5 checkintegrity:数据完整性检查(含退出码语义)
对应后台「配置 → 数据一致性检查」的工具,命令行版自动应用全部「安全修复」且无需逐步确认。help checkintegrity 的官方说明(实测摘录):
DESCRIPTION
Runs LimeSurvey's "Check data integrity" tool (Configuration > Data consistency
check) and applies all safe automatic fixes, with no manual confirmation step,
including renumbering duplicate group/question sort orders. Repeats the check
until nothing is left to fix, or a safety cap is reached.
Old survey/participant list tables that still contain response data are reported
but never deleted automatically; use the admin UI's data redundancy check for those.
EXIT CODES
0 Clean pass, nothing left to fix.
1 Ran, but at least one fix could not be applied (see WARNING lines).
2 Did not converge within the pass limit; needs manual investigation.
实测健康实例:
$ php application/commands/console.php checkintegrity
No database action required.
$ echo $?
0
要点:含答卷数据的孤儿表永远不会被自动删除(安全边界),需人工在后台数据冗余检查页处置;退出码非 0 时按 WARNING 行与官方建议处理,可纳入巡检脚本(exit code 驱动告警)。
2.6 importsurvey / wipe / plugin / message
importsurvey:命令行导入问卷定义文件(.lss),与后台导入等价,批量初始化问卷时配合 API 更顺手(见第三章);wipe:删除指定问卷的全部数据(高危),等价后台「删除问卷数据」,执行前务必备份;plugin cron --interval=:触发插件定时任务(部分插件依赖 cron 调度);message <config-file>:翻译消息提取编译(框架命令,二次开发场景)。
三、RemoteControl API 实测
3.1 接口形态与认证
RemoteControl 是挂在 /index.php/admin/remotecontrol 的 RPC 接口(版本 2,官方手册 RemoteControl 2 API;另有遗留的 v1 RSAPI 与新增 REST API 可在插件中启用)。每次调用都是独立 HTTP POST,请求体为 JSON:
{"method": "<方法名>", "params": {…}, "id": <自增序号>}
首个调用固定是 get_session_key 换取会话密钥(等价登录),后续调用都带它,结束时 release_session_key 释放:
$ curl -s -X POST http://localhost:8137/index.php/admin/remotecontrol \
-H 'Content-Type: application/json' \
-d '{"method":"get_session_key","params":{"username":"admin","password":"q1w2e3r4"},"id":1}'
{"id":1,"result":"LDCbrQfDUXPYTOcqd~GSf~n5erEFet60","error":null}
会话密钥有时效(闲置过期后返回 Invalid session key,见 3.5 排障③),脚本里每次任务重新取新 key 最稳。
3.2 问卷管理:导入 → 列表 → 激活
导入问卷(.lss 文件 Base64 编码后作为参数):
$ python3 - <<'PY' | curl -s -X POST http://localhost:8137/index.php/admin/remotecontrol -H 'Content-Type: application/json' -d @- | python3 -m json.tool
import base64, json
data = base64.b64encode(open('survey.lss','rb').read()).decode()
print(json.dumps({"method":"import_survey",
"params":{"sSessionKey":"<会话密钥>","sImportData":data,
"sSurveyName":"Builder Smoke Test","sSurveyID":None},
"id":3}))
PY
{
"id": 3,
"result": "62831",
"error": null
}
返回新问卷 SID 62831。导入后的问卷处于「未激活(草稿)」状态,list_surveys 可见(实测):
$ curl -s -X POST http://localhost:8137/index.php/admin/remotecontrol \
-H 'Content-Type: application/json' \
-d '{"method":"list_surveys","params":{"sSessionKey":"<会话密钥>","sUser":null},"id":4}'
{"id": 4, "result": [{"sid": 62831, "gsid": 1, "surveyls_title": "Builder Smoke Test",
"startdate": null, "expires": null, "active": "N"}], "error": null}
激活问卷:
$ curl -s -X POST http://localhost:8137/index.php/admin/remotecontrol \
-H 'Content-Type: application/json' \
-d '{"method":"activate_survey","params":{"sSessionKey":"<会话密钥>","iSurveyID":62831},"id":6}'
{"id": 6, "result": {"status": "OK"}, "error": null}
激活成功后数据库随即创建答卷数据表 lime_survey_62831(前缀 + SID 命名规则)。
3.3 令牌与参与者(受控问卷)
开放问卷可直接发放公开链接;受控问卷(匿名令牌模式)先激活令牌表再添加参与者。实测 activate_tokens 后 add_participants:
$ curl -s -X POST http://localhost:8137/index.php/admin/remotecontrol \
-H 'Content-Type: application/json' \
-d '{"method":"activate_tokens","params":{"sSessionKey":"<会话密钥>","iSurveyID":62831},"id":7}'
{"id": 7, "result": {"status": "OK"}, "error": null}
$ curl -s -X POST http://localhost:8137/index.php/admin/remotecontrol \
-H 'Content-Type: application/json' \
-d '{"method":"add_participants","params":{"sSessionKey":"<会话密钥>","iSurveyID":62831,
"aParticipantData":[{"email":"alice@example.com","firstname":"Alice"}],"bCreateToken":true},"id":8}'
{"id": 8, "result": [{"sent": "N", "remindersent": "N", "remindercount": 0, "completed": "N",
"usesleft": 1, "emailstatus": "OK", "email": "alice@example.com", "firstname": "Alice",
"token": "84r1fYzO4LUiuiW", "lastname": "", "tid": "1", ...}], "error": null}
返回的 token(如 84r1fYzO4LUiuiW)就是受访者的专属作答链接令牌:/index.php/62831?token=84r1fYzO4LUiuiW。
3.4 字段映射与答卷写入/导出
get_fieldmap:拿到问卷数据表的字段映射(系统字段 + 题目字段),是编程写入答卷前的对照表:
$ curl -s -X POST http://localhost:8137/index.php/admin/remotecontrol \
-H 'Content-Type: application/json' \
-d '{"method":"get_fieldmap","params":{"sSessionKey":"<会话密钥>","iSurveyID":62831},"id":10}'
{"id": 10, "result": {"id": {"fieldname": "id", "sid": 62831, "type": "id",
"question": "Response ID", ...}, "submitdate": {"fieldname": "submitdate", ...},
"lastpage": {...}, "startlanguage": {...}, "seed": {...}, "token": {...}, ...}, "error": null}
add_response:按字段映射直写一条答卷,返回答卷 ID:
$ curl -s -X POST http://localhost:8137/index.php/admin/remotecontrol \
-H 'Content-Type: application/json' \
-d '{"method":"add_response","params":{"sSessionKey":"<会话密钥>","iSurveyID":62831,
"responseData":{"usage":"Y","detail":"API smoke","rating":"5"}},"id":11}'
{"id": 11, "result": "1", "error": null}
export_responses:导出答卷数据(Base64 编码的文件内容),支持 csv/xls/pdf/json 与表头/答案形态参数:
$ curl -s -X POST http://localhost:8137/index.php/admin/remotecontrol \
-H 'Content-Type: application/json' \
-d '{"method":"export_responses","params":{"sSessionKey":"<会话密钥>","iSurveyID":62831,
"sDocumentType":"csv","sLanguageCode":"en","sCompletionStatus":"all",
"sHeadingType":"code","sResponseType":"short"},"id":12}' | \
python3 -c "import sys,json,base64;print(base64.b64decode(json.load(sys.stdin)['result']).decode())"
"id";"submitdate";"lastpage";"startlanguage";"seed";"token";"quota_exit";"usage";"detail";"rating"
"1";"2026-10-28 00:19:35";;"en";;;;;;
"2";"1980-01-01 00:00:00";"1";"en";"1642997305";;;;;;
CSV 带 BOM 头;submitdate 为 1980-01-01 00:00:00 是 LimeSurvey 标记「未完成答卷」的哨兵值,统计口径里要注意区分(sCompletionStatus 用 complete 可只导已完成)。
3.5 API 排障实录
- 调用不存在的方法 → HTTP 500:方法名拼错(实测
getDescription)触发 500,debug 开启时错误页为TypeError: call_user_func(): Argument #1 ($callback) must be a valid callback, class RemoteControl does not have a method "getDescription"(插件管理器分发链路抛出,见部署篇排障实录④)。RemoteControl 方法分发不是规范的「JSON error 返回」,方法名务必对照官方清单。 - HTTP 200 但响应体为空:多见于实例安装不完整/异常状态(本文实测发生于向导安装的新实例)。先确认安装完整(后台可登录、数据库表齐全),再重试 API。
{"status": "Invalid session key", "error_code": "ERR_INVALID_SESSION"}:会话密钥过期(实测复现:闲置后的旧 key 调 export_responses 即返回此错误)。重新get_session_key即可;长任务脚本应在收到该状态时自动重取。- 权限:会话密钥继承登录账号权限;普通用户账号调用管理类方法会被拒绝。批量脚本建议用专用运维账号并定期
release_session_key。
四、备份与恢复
4.1 备份三件套
| 对象 | 内容 | 获取方式 |
|---|---|---|
| 数据库 | 全部 lime_* 表 | mariadb-dump(MySQL 系为 mysqldump) |
| 应用上传目录 | upload/:主题、插件、问卷附件、签名图片 | 打包目录 |
| 加密密钥 | application/config/security.php | 拷贝文件(与数据库成对,缺一密文即废) |
数据库侧实测(导出 111 KB、61 张 CREATE TABLE):
$ mariadb-dump -u limesurvey -p<数据库密码> --single-transaction --routines limesurvey > ls_backup.sql
$ ls -lh ls_backup.sql
-rw-r--r-- 1 root root 111K Oct 28 10:09 ls_backup.sql
$ grep -c 'CREATE TABLE' ls_backup.sql
61
应用上传目录打包(示例为部署目录下的 upload):
$ tar -czf upload_$(date +%F).tgz upload/
例行建议:数据库每日 dump(--single-transaction 保证 InnoDB 一致性快照)+ upload 目录每日增量/每周全量 + security.php 一次归档多处存放。
4.2 恢复实测(含排障)
恢复到新库验证(演练到全新库 limesurvey_restore):
$ mariadb -u root -p<root密码> -e "CREATE DATABASE limesurvey_restore CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"
$ mariadb -u limesurvey -p<数据库密码> limesurvey_restore < ls_backup.sql
(无回显,但随后核对为 0 张表——导入实际失败)
实测排障点:用应用连接账号(limesurvey)导入新库失败且无报错回显——该账号的授权范围只覆盖原库(部署时 MARIADB_DATABASE 初始化的授权),对新库无建表权限,导入语句被静默拒绝。恢复操作应使用数据库 root 账号(或提前对新库 GRANT 全权限):
$ mariadb -u root -p<root密码> limesurvey_restore < ls_backup.sql
$ mariadb -u root -p<root密码> -e "SELECT
(SELECT COUNT(*) FROM information_schema.tables WHERE table_schema='limesurvey') AS src,
(SELECT COUNT(*) FROM information_schema.tables WHERE table_schema='limesurvey_restore') AS rst;"
src rst
61 61
$ mariadb -u root -p<root密码> limesurvey_restore -e "SELECT uid,username FROM lime_users;"
uid username
1 admin
表数 61 → 61、管理员记录完整,恢复链路验证通过。恢复到生产库的完整动作:停写(维护窗口)→ 导入 dump → 回放 security.php → 校验 checkintegrity exit 0 → 首页/API 冒烟。
4.3 迁移场景补充
跨主机迁移 = 备份三件套落新机 + config.php 改连接信息(或环境变量重注入)+ updatedb + checkintegrity。密钥与数据库必须同批迁移,混搭新旧密钥文件是最常见的事故源。
五、日常巡检清单
| 检查项 | 命令/位置 | 健康标准 |
|---|---|---|
| 应用存活 | curl -s -o /dev/null -w '%{http_code}' http://<站点>/ | 200 |
| RPC 探活 | get_session_key(3.1) | error: null |
| 数据完整性 | console.php checkintegrity | exit 0,No database action required. |
| 数据库结构版本 | console.php updatedb | no need update : DB is up-to-date |
| 磁盘 | 部署目录 du -sh upload/ mariadb/data/ | 增速平稳,附件配额内 |
| 备份新鲜度 | 备份产物时间戳 | 当日 dump + 周期性恢复演练 |
六、排障速查
| 症状 | 定位 | 处置 |
|---|---|---|
| API 500 | 方法名核对(3.5①) | 对照官方 RemoteControl 2 API 清单 |
| API 200 空响应 | 实例安装完整性(3.5②) | 重验安装链路,必要时重装实例 |
| Invalid session key | 密钥过期(3.5③) | 重取 get_session_key |
| 改镜像/程序后数据表报版本错 | 结构未升级 | 跑 console.php updatedb |
| 管理员密码丢失 | — | console.php resetpassword <user> <newpass> |
| 恢复库后表为空 | 账号无授权(4.2) | 换 root 导入或先 GRANT |
| 问卷导出 CSV 打开乱码 | 编码 | CSV 自带 BOM,确认编辑器按 UTF-8 解析 |
七、参考链接
- 官方手册 · RemoteControl 2 API(方法全集):https://manual.limesurvey.org/RemoteControl_2_API
- 官方手册 · Managing users / 备份与恢复:https://manual.limesurvey.org/Backups_of_the_database_and_configurations
- 官方手册 · Check data integrity:https://manual.limesurvey.org/Check_data_integrity
- 镜像 README(entrypoint 自动安装与
console.php联动):https://hub.docker.com/r/martialblog/limesurvey - 本专栏关联篇目:《LimeSurvey 介绍与选型指南》、《LimeSurvey 7.7 Docker Compose 部署实战》、《LimeSurvey 配置参数详解》