LimeSurvey 常用命令与运维实战

LimeSurvey 7.7 常用命令与运维实战:console.php 十八命令实测(install/updatedb/resetpassword/checkintegrity)、RemoteControl API 全链路(会话认证/激活/令牌/答卷/导出)、备份恢复演练与巡检速查,含会话过期等排障实录。

LimeSurveyLimeSurvey问卷调查2026/10/28

LimeSurvey 常用命令与运维实战

版本基线:LimeSurvey Community Edition 7.7.0(martialblog/limesurvey:7.7.0-261020-apache),实例经 《LimeSurvey 7.7 Docker Compose 部署实战》 完成部署安装 实测环境:应用根目录 /var/www/html,管理员账号 admin,示例问卷 ID 62831(问卷名 Builder Smoke Test,含单选 L + 短文本 S + 数值 5 三题) 读者前置:已完成部署安装与基本配置(配置体系见 《LimeSurvey 配置参数详解》)

一、运维三支柱总览

LimeSurvey 的日常运维围绕三条主线展开:

支柱入口典型任务
命令行application/commands/console.php(应用根目录)安装/升级/改密/数据完整性检查/问卷导入
RemoteControl APIPOST /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 排障实录

  1. 调用不存在的方法 → 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 返回」,方法名务必对照官方清单。
  2. HTTP 200 但响应体为空:多见于实例安装不完整/异常状态(本文实测发生于向导安装的新实例)。先确认安装完整(后台可登录、数据库表齐全),再重试 API。
  3. {"status": "Invalid session key", "error_code": "ERR_INVALID_SESSION"}:会话密钥过期(实测复现:闲置后的旧 key 调 export_responses 即返回此错误)。重新 get_session_key 即可;长任务脚本应在收到该状态时自动重取。
  4. 权限:会话密钥继承登录账号权限;普通用户账号调用管理类方法会被拒绝。批量脚本建议用专用运维账号并定期 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 checkintegrityexit 0,No database action required.
数据库结构版本console.php updatedbno 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 解析

七、参考链接