ProjeQtOr 13.1.1 常用 CLI 与运维命令详解

ProjeQtOr 13.1.1 运维命令手册:systemctl 服务管理、版本巡检、Cron 启停与状态文件、mysqldump 备份与恢复演练、日志过滤、数据库与权限巡检、升级回滚,含真实回显与故障处置。

ProjeQtOrProjeQtOrPHPMariaDBnginx2026/10/28

ProjeQtOr 13.1.1 常用 CLI 与运维命令详解

目标:把 ProjeQtOr 13.1.1 日常运维所需的命令收拢成一本可执行的手册,覆盖服务管理、版本巡检、Cron 调度、备份恢复、日志排查、数据库巡检、权限与磁盘检查、升级回滚,并附真实回显与故障处置顺序。

版本查询日期:2026-10-28;实测日期:2026-10-28。

演示管理账号:admin,密码:q1w2e3r4。

配套文档:《ProjeQtOr 13.1.1 Ubuntu 22.04 安装指南》、《ProjeQtOr 13.1.1 配置参数详解》。

一、环境与命令基础

1.1 实测环境

$ php -v | head -1
PHP 8.1.2-1ubuntu2.28 (cli) (built: Oct 19 2026 18:54:45) (NTS)
$ nginx -v 2>&1
nginx version: nginx/1.18.0 (Ubuntu)
$ mariadb --version
mariadb  Ver 15.1 Distrib 10.6.23-MariaDB, for debian-linux-gnu (x86_64) using  EditLine wrapper
$ grep PRETTY_NAME /etc/os-release
PRETTY_NAME="Ubuntu 22.04.5 LTS"
项目取值
代码目录/var/www/projeqtor
配置与数据目录/var/lib/projeqtor
日志/var/lib/projeqtor/log/projeqtor_20261028.log
Cron 状态文件/var/www/projeqtor/files/cron
数据库projeqtor,账号 projeqtor
运行用户www-data

1.2 命令执行的两种身份

$ id www-data
uid=33(www-data) gid=33(www-data) groups=33(www-data)
$ whoami
root

服务管理、目录授权、数据库备份用 root;凡是涉及应用目录写入、Cron 文件、parameters.php 校验的命令,用 sudo -u www-data 执行,才能复现真实权限下的结果。用 root 跑通、用 www-data 跑不通,是最常见的“配置没错但功能不可用”的原因。

1.3 环境自检脚本

$ for s in nginx php8.1-fpm mariadb; do printf "%-14s %s %s\n" "$s" "$(systemctl is-enabled $s)" "$(systemctl is-active $s)"; done
nginx          enabled active
php8.1-fpm     enabled active
mariadb        enabled active

三条都是 enabled active 才继续后面的运维操作。

二、服务管理命令

2.1 查看服务状态

systemctl status 会带出进程树,适合人工查看;脚本巡检用 show 更稳定:

$ for u in nginx php8.1-fpm mariadb; do echo "== $u"; systemctl show $u -p ActiveState -p UnitFileState -p MainPID; done
== nginx
MainPID=14267
ActiveState=active
UnitFileState=enabled
== php8.1-fpm
MainPID=14262
ActiveState=active
UnitFileState=enabled
== mariadb
MainPID=38044
ActiveState=active
UnitFileState=enabled

MainPID 变化说明服务重启过;升级排障时对比 PID 能确认是否真的重载成功。

2.2 启动、停止、重载的取舍

操作命令影响
启动并设为开机自启systemctl enable --now nginx立即启动,重启后自动拉起
停止systemctl stop nginx断开所有连接,维护窗口使用
重载配置systemctl reload nginx不中断连接,改配置后首选
重启服务systemctl restart php8.1-fpm中断进行中的请求,清理 OPcache
查看是否开机自启systemctl is-enabled nginx输出 enabled / disabled

PHP 代码或 php.ini 改动用 reload;升级 PHP 扩展、改 FPM 池结构用 restart。Nginx 改 upstream 或站点配置用 reload 即可。

2.3 配置语法检查

$ sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
$ sudo php-fpm8.1 -t
[27-Oct-2026 18:12:39] NOTICE: configuration file /etc/php/8.1/fpm/php-fpm.conf test is successful

先 -t 再 reload,避免把语法错误带进生产。php-fpm8.1 -t 只校验 FPM 主配置,php.ini 的语法错误要到实际请求时才会暴露。

2.4 服务级日志

$ journalctl -u php8.1-fpm -n 5 --no-pager
Oct 27 18:09:34 projeqtor-lab systemd[1]: Reloaded The PHP 8.1 FastCGI Process Manager.
Oct 27 18:09:42 projeqtor-lab systemd[1]: Reloading The PHP 8.1 FastCGI Process Manager...
Oct 27 18:09:42 projeqtor-lab systemd[1]: Reloaded The PHP 8.1 FastCGI Process Manager.
Oct 27 18:09:44 projeqtor-lab systemd[1]: Reloading The PHP 8.1 FastCGI Process Manager...
Oct 27 18:09:44 projeqtor-lab systemd[1]: Reloaded The PHP 8.1 FastCGI Process Manager.

这里只有服务生命周期事件,应用报错在 /var/lib/projeqtor/log/,两者要分开看。

三、安装、升级与版本巡检

3.1 安装包校验

$ curl -skL -A 'Wget/1.21' -o projeqtorV13.1.1.zip https://freefr.dl.sourceforge.net/project/projectorria/projeqtorV13.1.1.zip
$ ls -l projeqtorV13.1.1.zip
-rw-r--r-- 1 root root 117427304 Oct 28 01:23 projeqtorV13.1.1.zip
$ sha256sum projeqtorV13.1.1.zip
c52b01a8e8b561198d0af77d35cc891c31be0e184145ef76228cd6851ef95e30  projeqtorV13.1.1.zip

-k 仅用于下载站点证书链异常时的临时绕过,校验哈希通过后再部署,不能因为跳过证书校验就跳过完整性校验。

3.2 解包与部署

$ sudo unzip -q projeqtorV13.1.1.zip -d /tmp/projeqtor-pkg
$ sudo cp -a /tmp/projeqtor-pkg/projeqtor/. /var/www/projeqtor/
$ sudo chown -R www-data:www-data /var/www/projeqtor
$ sudo find /var/www/projeqtor -type d -exec chmod 755 {} \;
$ sudo find /var/www/projeqtor -type f -exec chmod 644 {} \;

覆盖部署时保留 tool/parametersLocation.php,否则应用会丢失配置指针。

3.3 版本巡检四件套

$ curl -sI http://127.0.0.1/ | head -5
HTTP/1.1 200 OK
Server: nginx/1.18.0 (Ubuntu)
Date: Tue, 27 Oct 2026 18:09:52 GMT
Content-Type: text/html; charset=UTF-8
Connection: keep-alive
$ mariadb -u projeqtor -pq1w2e3r4 projeqtor -e "SELECT parameterValue AS dbVersion FROM parameter WHERE parameterCode='dbVersion';"
dbVersion
V13.1.1
$ grep -n "DATABASE UPDATE COMPLETED" /var/lib/projeqtor/log/projeqtor_20261028.log | tail -1
7564:2026-10-28 01:29:46.773 ===== TRACE ===== DATABASE UPDATE COMPLETED TO VERSION V13.1.1
$ ls -l /var/lib/projeqtor/config/parameters.php
-rw-r--r-- 1 www-data www-data 564 Oct 27 17:29 /var/lib/projeqtor/config/parameters.php

四项分别验证:Web 服务在响应、数据库版本、升级日志、配置文件存在。四项都吻合才说明版本一致;只看到 HTTP 200 不代表数据库已经升级。

四、Cron 运维

4.1 运行机制

ProjeQtOr 的 Cron 不是系统 crontab 里的定时任务,而是一个常驻 PHP 进程,由 tool/cronRun.php 启动,循环内按秒倒计时执行日期告警、导入扫描、收邮件等任务。启动方式必须是 HTTP 请求,CLI 直接执行不可用。

4.2 启动与观察

$ curl -s --max-time 4 -o /tmp/cron.out -w "http=%{http_code} time=%{time_total}\n" -b /tmp/cookies.txt http://127.0.0.1/tool/cronRun.php
http=000 time=4.000892
$ sudo cat /var/www/projeqtor/files/cron/RUNNING
1793124514|37855|6ae0e8a241cb96.19165710

http=000 不是失败,而是客户端主动超时:Cron 进程进入常驻循环,请求本身不会返回。RUNNING 的内容依次是时间戳、进程 PID、唯一标识,用 | 分隔。进程存活期间该文件会被周期性刷新。

$ sudo tail -3 /var/www/projeqtor/files/cron/HISTORY
2026-10-28 01:37:13 | 1 | run 
2026-10-28 01:37:43 |  | stop 
2026-10-28 02:08:34 | 1 | run 
$ tail -4 /var/lib/projeqtor/log/projeqtor_20261028.log
2026-10-28 02:08:34.270 ===== TRACE ===== Cron started at 28/10/2026 02:08:34

HISTORY 每行是「时间 | 操作者 ID | 动作」,通过页面启动时操作者是 1,通过 STOP 文件停止时操作者为空。

4.3 正常停止

不要在页面上等请求结束,正确做法是写 STOP 标志:

$ sudo touch /var/www/projeqtor/files/cron/STOP
$ sudo chown www-data:www-data /var/www/projeqtor/files/cron/STOP
$ sleep 12
$ ls /var/www/projeqtor/files/cron/
DELAYS
HISTORY
index.php
$ sudo tail -3 /var/www/projeqtor/files/cron/HISTORY
2026-10-28 01:37:43 |  | stop 
2026-10-28 02:08:34 | 1 | run 
2026-10-28 02:08:44 |  | stop 

停止延迟约等于一个 cronSleepTime 周期(实测 10 秒)。RUNNING 与 STOP 同时消失、HISTORY 新增 stop,才算干净退出。强制 kill 进程会留下 RUNNING,下次启动可能被判定为重复实例。

4.4 查看当前周期

$ sudo cat /var/www/projeqtor/files/cron/DELAYS
SleepTime=10|CheckDates=30|CheckImport=60|CheckEmails=-1

这是运行实例的周期快照,改参数后必须重启 Cron 才生效。RUNNING 超过 30 分钟未刷新会被判定为僵死,程序自动清理并允许重新启动。

4.5 批量模式与自动重启

批量模式由 AUTO 文件触发,文件内容格式为 key|用户ID,例如 dailybatch|1;随后带上 ?autorestartkey=dailybatch 访问 tool/cronRun.php,进程会以该用户身份运行且跳过管理员权限校验。AUTO 只在批量模式下生成,实测普通启动后该文件不存在。该模式适合由系统定时器在每个维护窗口拉起一次批处理,使用前先确认 AUTO 内容与调用参数严格一致,否则会退回普通启动路径。

4.6 CLI 方式为什么不可用

从代码目录直接执行:

$ cd /var/www/projeqtor && sudo -u www-data php tool/cronRun.php
PHP Warning:  require_once(../tool/projeqtor.php): Failed to open stream: No such file or directory in /var/www/projeqtor/tool/cronRun.php on line 39
PHP Fatal error:  Uncaught Error: Failed opening required '../tool/projeqtor.php' (include_path='.:/usr/share/php') in /var/www/projeqtor/tool/cronRun.php:39
Stack trace:
#0 {main}
  thrown in /var/www/projeqtor/tool/cronRun.php on line 39

切到 tool 目录再执行,能过 include,但会因为缺少会话上下文被应用拒绝:

$ cd /var/www/projeqtor/tool && sudo -u www-data php cronRun.php
<input type="hidden" id="lastOperation" name="lastOperation" value="testConnection"><input type="hidden" id="lastOperationStatus" name="lastOperationStatus" value="ERROR"><div class="messageERROR" >Connection Lost. Please reconnect.</div>

结论:Cron 只能通过 Web 入口启动。需要定时启停时,用系统定时器调用 curl 访问该入口并写 STOP 标志,不要改成 php 命令行。

4.7 浏览器 504 与 Cron 存活的关系

浏览器打开 tool/cronRun.php 后约 60 秒会收到 504,这是 Nginx 的 fastcgi_read_timeout 触发,不代表 Cron 退出。判断依据始终是 RUNNING 与 HISTORY,不是浏览器页面。

五、备份与恢复

5.1 代码备份

$ sudo tar -czf /var/backups/projeqtor-code-20261028.tar.gz -C /var/www projeqtor
$ ls -lh /var/backups/projeqtor-code-20261028.tar.gz
-rw-r--r-- 1 root root 105M Oct 27 18:07 /var/backups/projeqtor-code-20261028.tar.gz

代码目录实测 268 MB,压缩后 105 MB。备份代码的意义在于回滚版本,配置与附件不在这份包里,必须单独备份。

5.2 数据库备份

$ S=$(date +%s%N); mysqldump -u projeqtor -pq1w2e3r4 --single-transaction --routines --triggers projeqtor > /var/backups/projeqtor-db-20261028.sql; E=$(date +%s%N); echo "elapsed_ms=$(( (E-S)/1000000 ))"
elapsed_ms=307
$ ls -lh /var/backups/projeqtor-db-20261028.sql
-rw-r--r-- 1 root root 725K Oct 27 18:07 /var/backups/projeqtor-db-20261028.sql
$ grep -c "^CREATE TABLE" /var/backups/projeqtor-db-20261028.sql
357

三个参数的作用:--single-transaction 保证 InnoDB 一致性快照且不锁表;--routines 导出存储过程与函数;--triggers 导出触发器。少任何一个,恢复后都可能缺对象。

5.3 附件与配置备份

$ sudo tar -czf /var/backups/projeqtor-data-20261028.tar.gz -C /var/lib projeqtor
$ ls -lh /var/backups/projeqtor-data-20261028.tar.gz
-rw-r--r-- 1 root root 48K Oct 27 18:12 /var/backups/projeqtor-data-20261028.tar.gz

/var/lib/projeqtor 里包含 config/parameters.php、日志、附件、文档与报表临时文件。实测环境附件为空,压缩包只有 48 KB;附件增长后这个包会同步变大。附件是业务资产,必须与数据库同批次备份,只备数据库会导致附件记录存在但文件缺失。

5.4 恢复演练

在独立库上先验证,不要直接覆盖生产库:

$ sudo mariadb -u root -e "DROP DATABASE IF EXISTS projeqtor_restore; CREATE DATABASE projeqtor_restore DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci; GRANT ALL ON projeqtor_restore.* TO 'projeqtor'@'localhost'; FLUSH PRIVILEGES;"
$ S=$(date +%s%N); mariadb -u projeqtor -pq1w2e3r4 projeqtor_restore < /var/backups/projeqtor-db-20261028.sql; E=$(date +%s%N); echo "restore_ms=$(( (E-S)/1000000 ))"
restore_ms=1111
$ mariadb -u projeqtor -pq1w2e3r4 projeqtor_restore -e "SELECT COUNT(*) AS tbls FROM information_schema.tables WHERE table_schema='projeqtor_restore'; SELECT parameterValue AS dbVersion FROM parameter WHERE parameterCode='dbVersion'; SELECT COUNT(*) AS users FROM resource WHERE isUser=1;"
tbls
357
dbVersion
V13.1.1
users
2

恢复耗时 1.1 秒、357 张表、版本 V13.1.1、2 个可登录用户,说明备份可用。生产恢复时先停 Nginx 与 Cron,导入后再启动,避免半恢复状态下写入新数据。

5.5 备份计划建议

$ sudo crontab -l
0 2 * * * /usr/local/bin/projeqtor-backup.sh >> /var/log/projeqtor-backup.log 2>&1

脚本内依次执行数据库导出、附件打包、删除 14 天前的旧备份。备份文件不要与数据放在同一块磁盘,至少复制到独立存储。恢复演练建议每季度做一次,只备份不演练等于没有备份。

六、日志与排障命令

6.1 定位日志文件

$ ls -lh /var/lib/projeqtor/log/
total 544
-rw-r--r-- 1 www-data www-data    348 Oct 27 17:36 projeqtor_20261027.log
-rw-r--r-- 1 www-data www-data 551827 Oct 27 17:46 projeqtor_20261028.log

文件名按 PHP 时区日期生成,${date} 由程序替换为 Ymd。

6.2 常用过滤

$ grep -c "Connection to Database failed" /var/lib/projeqtor/log/projeqtor_20261028.log
2
$ grep -c "Cron normally stopped" /var/lib/projeqtor/log/projeqtor_20261028.log
3
$ grep -c "NEW CONNECTED USER" /var/lib/projeqtor/log/projeqtor_20261028.log
6
$ grep "Connection to Database failed" /var/lib/projeqtor/log/projeqtor_20261028.log | tail -1
2026-10-28 02:09:08.234 ***** ERROR ***** [] [1] SQL ERROR : Connection to Database failed 

计数用于趋势判断,定位问题仍要看上下文。数据库连接、登录、Cron 三类事件是运维最常查的。

6.3 日志格式

2026-10-28 02:09:43.515 ..... SCRIPT .... [1] 127.0.0.1 securityGetAccessRight(menuName=menuProject, accessType=read, obj=, user=)
2026-10-28 02:08:44.278 ===== TRACE ===== Cron normally stopped at 28/10/2026 02:08:44
2026-10-28 02:09:08.234 ***** ERROR ***** [] [1] SQL ERROR : Connection to Database failed 

结构是「时间.毫秒 标记 [用户ID] 消息」。[1] 是 admin 的用户 ID,[] 表示尚未建立用户上下文(例如数据库连不上时)。SCRIPT 行只在本级别开启时才写入,排查权限问题时很有用。

6.4 实时跟踪

$ sudo tail -f /var/lib/projeqtor/log/projeqtor_20261028.log

复现问题时保持一个窗口跟踪,另一个窗口执行操作,能直接看到「操作 → 日志」的对应关系。排查结束用 Ctrl+C 退出,不要关闭窗口了事。

6.5 排查顺序

  1. 页面是否 200:curl -sI http://127.0.0.1/。
  2. 数据库是否可连:日志里搜 Connection to Database failed。
  3. 应用是否报错:日志里搜 ERROR,看最近 20 行。
  4. 服务是否重启:journalctl -u php8.1-fpm -n 20 --no-pager。
  5. 磁盘是否满:df -h、du -sh /var/lib/projeqtor/*。

七、数据库日常运维

7.1 连接与版本

$ mariadb -u projeqtor -pq1w2e3r4 projeqtor -e "SELECT VERSION();"
VERSION()
10.6.23-MariaDB-0ubuntu0.22.04.1
$ mariadb -u projeqtor -pq1w2e3r4 projeqtor -e "SELECT parameterValue AS dbVersion FROM parameter WHERE parameterCode='dbVersion';"
dbVersion
V13.1.1

VERSION() 是数据库引擎版本,dbVersion 是应用数据库结构版本,两者不要混淆。升级应用后只应看到后者变化。

7.2 容量与表数量

$ mariadb -u projeqtor -pq1w2e3r4 projeqtor -e "SELECT COUNT(*) AS tables FROM information_schema.tables WHERE table_schema='projeqtor'; SELECT ROUND(SUM(data_length+index_length)/1024/1024,1) AS size_mb FROM information_schema.tables WHERE table_schema='projeqtor';"
tables
357
size_mb
14.2

357 张表是 V13.1.1 的完整结构;表数量明显偏少通常意味着升级未执行完。

7.3 连接与活动会话

$ mariadb -u projeqtor -pq1w2e3r4 projeqtor -e "SHOW PROCESSLIST;"
Id	User	Host	db	Command	Time	State	Info	Progress
36	projeqtor	localhost	projeqtor	Query	0	starting	SHOW PROCESSLIST	0.000

出现大量 Sleep 且 Time 很大,说明连接池或长事务没有释放;出现 Waiting for table metadata lock 说明有 DDL 被阻塞。

7.4 大表巡检

$ mariadb -u projeqtor -pq1w2e3r4 projeqtor -e "SELECT table_name, table_rows, ROUND((data_length+index_length)/1024/1024,2) AS mb FROM information_schema.tables WHERE table_schema='projeqtor' ORDER BY data_length+index_length DESC LIMIT 5;"
table_name	table_rows	mb
habilitation	2262	0.25
requirement	0	0.23
expense	0	0.22
changerequest	0	0.19
work	0	0.19

table_rows 是估算值,InnoDB 下会有偏差,判断体积以 mb 列为准。附件不存库内,所以数据库体积通常远小于代码目录。

7.5 维护命令

$ sudo mariadb-check -u projeqtor -pq1w2e3r4 --databases projeqtor
$ sudo mariadb -u projeqtor -pq1w2e3r4 projeqtor -e "ANALYZE TABLE work, assignment, expense;"

mariadb-check 用于一致性检查,建议在低峰期执行;ANALYZE TABLE 刷新统计信息,改善执行计划。大表重建(OPTIMIZE TABLE)会锁表,必须安排维护窗口。

八、文件、权限与磁盘巡检

8.1 磁盘占用

$ du -sh /var/www/projeqtor /var/lib/projeqtor
268M	/var/www/projeqtor
676K	/var/lib/projeqtor
$ df -h /var/www | tail -1
overlay         295G  128G  152G  46% /

代码 268 MB,数据目录 676 KB(附件为空时)。附件增长是磁盘占用的主要变量,建议对 files/attach 单独做容量告警。

8.2 权限审计

$ sudo find /var/www/projeqtor -maxdepth 1 ! -user www-data -print
$ sudo find /var/lib/projeqtor -maxdepth 2 ! -user www-data -print
$ sudo find /var/lib/projeqtor -type f -name "*.php" -perm /o+w -print

前两条找出属主不对的文件,第三条找出组外可写的 PHP 文件。升级或手工复制后最容易出现属主错乱,表现为“页面空白但日志无报错”。

8.3 权限修复

$ sudo chown -R www-data:www-data /var/www/projeqtor /var/lib/projeqtor
$ sudo find /var/www/projeqtor -type d -exec chmod 755 {} \;
$ sudo find /var/www/projeqtor -type f -exec chmod 644 {} \;
$ sudo chmod 640 /var/lib/projeqtor/config/parameters.php
$ sudo chmod 755 /var/lib/projeqtor/log /var/lib/projeqtor/files/attach /var/lib/projeqtor/files/documents /var/lib/projeqtor/files/report

parameters.php 单独收紧到 640,因为它含数据库明文密码。

8.4 临时文件清理

$ sudo find /var/lib/projeqtor/files/report -type f -mtime +7 -delete
$ sudo find /var/lib/projeqtor/log -type f -mtime +14 -delete

报表临时文件 7 天、日志 14 天的保留期足够定位问题。删除前确认没有正在生成的报表,避免误删正在写入的文件。

8.5 会话文件

$ sudo ls /var/lib/php/sessions | wc -l
11

会话数量异常增长说明客户端没有正常登出或会话未回收。清理会话会让所有在线用户重新登录,操作前通知。

九、升级与回滚命令清单

9.1 升级前

$ sudo tar -czf /var/backups/projeqtor-code-$(date +%F).tar.gz -C /var/www projeqtor
$ mysqldump -u projeqtor -pq1w2e3r4 --single-transaction --routines --triggers projeqtor > /var/backups/projeqtor-db-$(date +%F).sql
$ sudo cp -a /var/www/projeqtor/tool/parametersLocation.php /var/backups/parametersLocation.php
$ sudo touch /var/www/projeqtor/files/cron/STOP

先停 Cron,再备份,顺序不能反。

9.2 覆盖代码

$ sudo systemctl stop nginx
$ sudo unzip -q projeqtorV13.1.1.zip -d /tmp/projeqtor-new
$ sudo cp -a /tmp/projeqtor-new/projeqtor/. /var/www/projeqtor/
$ sudo cp -a /var/backups/parametersLocation.php /var/www/projeqtor/tool/parametersLocation.php
$ sudo chown -R www-data:www-data /var/www/projeqtor
$ sudo systemctl start nginx

9.3 升级后验证

$ curl -sI http://127.0.0.1/ | head -1
HTTP/1.1 200 OK
$ mariadb -u projeqtor -pq1w2e3r4 projeqtor -e "SELECT parameterValue AS dbVersion FROM parameter WHERE parameterCode='dbVersion';"
dbVersion
V13.1.1
$ grep "DATABASE UPDATE COMPLETED" /var/lib/projeqtor/log/projeqtor_20261028.log | tail -1
7564:2026-10-28 01:29:46.773 ===== TRACE ===== DATABASE UPDATE COMPLETED TO VERSION V13.1.1

数据库升级由管理员首次登录触发,不是覆盖代码时自动执行。登录一次再查 dbVersion,版本没变说明升级脚本没有跑完,先看日志再决定是否回滚。

9.4 回滚

$ sudo systemctl stop nginx
$ sudo rm -rf /var/www/projeqtor
$ sudo tar -xzf /var/backups/projeqtor-code-20261028.tar.gz -C /var/www
$ sudo mariadb -u projeqtor -pq1w2e3r4 projeqtor < /var/backups/projeqtor-db-20261028.sql
$ sudo chown -R www-data:www-data /var/www/projeqtor
$ sudo systemctl start nginx

回滚必须代码与数据库同版本,只回滚代码会让旧程序读到新结构,出现字段缺失错误。

十、命令速查表

场景命令实测片段
服务状态systemctl show nginx -p ActiveStateActiveState=active
配置检查nginx -tsyntax is ok
版本巡检SELECT parameterValue FROM parameter WHERE parameterCode='dbVersion'V13.1.1
表数量SELECT COUNT(*) FROM information_schema.tables WHERE table_schema='projeqtor'357
库体积SELECT ROUND(SUM(data_length+index_length)/1024/1024,1) ...14.2
启动 Croncurl http://127.0.0.1/tool/cronRun.php请求不返回,RUNNING 出现
停止 Crontouch files/cron/STOP约 10 秒后 stop 入 HISTORY
全库备份mysqldump --single-transaction --routines --triggers725K、357 张表
恢复验证mariadb projeqtor_restore < dump.sql1111 ms
代码备份tar -czf ... -C /var/www projeqtor105M
日志跟踪tail -f /var/lib/projeqtor/log/projeqtor_20261028.log实时输出
磁盘检查df -h /var/www46% /
权限修复chown -R www-data:www-data无输出即成功

十一、常见故障与处置

11.1 页面正常返回但内容报数据库错误

$ sudo systemctl stop mariadb
$ curl -s -o /tmp/dbdown.html -w "http=%{http_code}\n" http://127.0.0.1/view/main.php
http=200
$ grep -o "SQLSTATE[^<]*" /tmp/dbdown.html | head -3
SQLSTATE[HY000] [2002] Connection refused

日志对应行:

2026-10-28 02:09:08.234 ***** ERROR ***** [] [1] SQL ERROR : Connection to Database failed 
2026-10-28 02:09:08.234 ***** ERROR ***** [] [1]   dns='mysql:host=127.0.0.1;port=3306;dbname=projeqtor'
2026-10-28 02:09:08.234 ***** ERROR ***** [] [1]   user='projeqtor'
2026-10-28 02:09:08.234 ***** ERROR ***** [] [1]   error=SQLSTATE[HY000] [2002] Connection refused

2002 是连不上实例,先 systemctl start mariadb;1045 是账号密码错误,查 parameters.php;1049 是库不存在。三者处置完全不同,按错误码分流。

11.2 502 Bad Gateway

Nginx 到 PHP-FPM 的 socket 不通。检查:

$ systemctl is-active php8.1-fpm
active
$ ls -l /run/php/php8.1-fpm.sock
srw-rw---- 1 www-data www-data 0 Oct 27 17:26 /run/php/php8.1-fpm.sock
$ sudo tail -20 /var/log/nginx/projeqtor_error.log

socket 不存在说明 FPM 没启动;权限不是 www-data 说明池配置里的 listen.owner 被改过。

11.3 Cron 看起来没跑

$ sudo cat /var/www/projeqtor/files/cron/RUNNING
$ sudo tail -5 /var/www/projeqtor/files/cron/HISTORY

RUNNING 存在但时间戳很旧(超过 30 分钟)说明进程僵死,写 STOP 后重新启动即可。RUNNING 不存在且 HISTORY 没有新的 run,说明启动请求没成功,先确认登录会话有效,再重试。

11.4 磁盘写满

$ df -h /var/www
$ sudo du -sh /var/lib/projeqtor/* | sort -h
$ sudo find /var/lib/projeqtor/files/attach -type f -size +100M -print

优先清理报表临时文件与旧日志,再考虑归档大附件。磁盘满时 PHP 会话写入也会失败,表现为随机退出登录。

11.5 日志目录不可写

应用会在页面提示 invalidLogDir 或 lockedLogDir。修复:

$ sudo mkdir -p /var/lib/projeqtor/log
$ sudo chown www-data:www-data /var/lib/projeqtor/log
$ sudo chmod 755 /var/lib/projeqtor/log

改完不需要重启,下一次请求即恢复写入。

11.6 附件上传失败

$ sudo -u www-data test -w /var/lib/projeqtor/files/attach && echo writable
writable
$ php -r "echo ini_get('upload_max_filesize'),' / ',ini_get('post_max_size'),PHP_EOL;"
100M / 100M

三处限制同时生效:目录可写、PHP upload_max_filesize/post_max_size、Nginx client_max_body_size。任何一处偏小都会导致上传失败或截断。

十二、参考链接

以上链接与版本信息查询日期均为 2026-10-28。