ITFlow 26.10 常用 CLI 命令与工具详解

ITFlow 26.10 命令行工具实测:cron.php 调度器与 9 个任务脚本逐个回显、setup_cli/update_cli/restore_cli 运维三件套用法、锁文件机制与排障实录。

ITFlowITFlow自托管2026/10/24

ITFlow 26.10 常用 CLI 命令与工具详解

目标:盘点 ITFlow 26.10 服务器侧的命令行工具——每分钟被 cron 拉起的任务调度器 cron/cron.php 及其 9 个注册任务脚本、scripts/ 下的三个官方运维脚本(安装/更新/恢复),给出逐个的直跑实测回显、运行身份纪律与故障实录。本文所有命令与回显均在 Ubuntu 22.04.5 LTS 实机实例上实测采集(ITFlow v26.10,git 标签)。

一、环境信息

项目值
操作系统Ubuntu 22.04.5 LTS
ITFlowv26.10(APP_VERSION = "26.10",数据库版本 2.7.9)
PHP CLI8.3.36
站点目录/var/www/html(属主 www-data:www-data)
数据库itflow(MariaDB 10.6.23,业务库前缀无、表 141 张)
cron 形态/etc/cron.d/itflow 每分钟拉起 cron/cron.php

安装部署过程(含 Web 向导与 setup_cli 静默安装两条路线)见 《Ubuntu 22.04 安装 ITFlow 26.10 指南》;文中涉及的 config.php 参数与 settings 表字段见 《ITFlow 26.10 配置参数详解》。

二、CLI 全景总览

ITFlow 是纯 PHP 应用,没有自研的 shell 二进制,其「CLI 形态」由两组 PHP 脚本构成(均为仓库自带,v26.10 实查):

组位置成员调用方式
后台任务族/var/www/html/cron/cron.php(调度器)+ nightly_tasks.php、mail_queue.php、ticket_email_parser.php、domain_refresher.php、certificate_refresher.php、backup.php、app_update.php、update_check.php、ticket_sla.php系统 cron 每分钟拉起 cron.php 统一派发;也可对单个脚本直跑排障
运维脚本族/var/www/html/scripts/setup_cli.php(静默安装)、update_cli.php(代码+数据库更新)、restore_cli.php(备份恢复)手工按需执行

💡 技术拓展:这类 PHP 应用的后台任务常见三种门派——应用内嵌触发(用户访问时顺带跑)、常驻队列进程(额外守护进程)、系统 cron 拉起脚本。ITFlow 选第三种:只要一条 * * * * * crontab,无新增常驻进程;代价是任务粒度的调度与状态要自己管——它把这些放在数据库 cron_jobs 表(见第四节),形成「系统 cron 管节奏、应用管语义」的双层结构。

统一纪律(实测教训沉淀,反复触发):

  1. 运行身份 = 站点文件属主 www-data。cron.php 及全部子脚本在 /tmp 建锁文件(命名 itflow_cron_<md5(脚本绝对路径)>.lock),并以 git 仓库形态自更新——root 手动直跑会留下 root 属主的锁文件与 .git 文件,随后 www-data 的系统调度立即被拒(实录见第七节 FAQ Q1/Q2);
  2. 手动排障用 sudo -u www-data php ... 或 su -s /bin/bash www-data -c 'php ...';
  3. 脚本直跑的工作目录不影响执行(脚本内部已处理路径),但保持 cd /var/www/html 再跑的习惯更稳。

三、调度器 cron.php 与任务注册表

3.1 调度器本体

cron/cron.php 是唯一需要 crontab 的入口,每分钟做一次「读注册表 → 判断哪些任务到期 → 逐个执行并记录」:

sudo -u www-data php /var/www/html/cron/cron.php

实测回显:无任何输出,退出码 0(正常时静默是设计行为——所有进度与状态都写进 cron_jobs 表而非 stdout)。

系统侧配合(/etc/cron.d/itflow,实测文件内容):

* * * * * www-data php /var/www/html/cron/cron.php >/dev/null

调度是否真的被拉起过,用两个证据核验(实测):

sudo mariadb -u root itflow -e "SELECT config_cron_last_dispatch_at FROM settings;"

实测回显:

config_cron_last_dispatch_at
2026-10-23 23:37:01
journalctl -u cron --no-pager | grep CMD | tail -2

实测回显(节选):

Oct 23 15:37:01 itflow-server CRON[27105]: (www-data) CMD (php /var/www/html/cron/cron.php >/dev/null)

3.2 任务注册表(cron_jobs 表,9 个任务实测全量)

sudo mariadb -u root itflow -e "SELECT cron_job_name, cron_job_schedule, cron_job_interval_minutes, cron_job_daily_at, cron_job_enabled, cron_job_last_status FROM cron_jobs ORDER BY cron_job_id;"

实测回显:

cron_job_name         cron_job_schedule  cron_job_interval_minutes  cron_job_daily_at  cron_job_enabled  cron_job_last_status
mail_queue            Interval           1                          NULL               1                 Stopped
ticket_email_parser   Interval           1                          NULL               1                 Stopped: Email Parser: Feature is not enabled - check Settings > Ticketing > Email-to-ticket parsing. See https://docs.itflow.org/ticket_email_parse  -- Quitting..
ticket_sla            Interval           1                          NULL               1                 Completed
domain_refresher      Daily              1                          04:00:00           1                 Stopped: Cron: is not enabled -- Quitting..
nightly_tasks         Daily              1                          03:00:00           1                 Stopped: Cron: is not enabled -- Quitting..
backup                Daily              1                          02:00:00           1                 Completed
certificate_refresher Daily              1                          03:30:00           1                 Stopped: Cron: is not enabled -- Quitting..
update_check          Daily              1                          02:30:00           1                 Stopped: Cron: is not enabled
app_update            Daily              1                          05:00:00           0                 NULL

要点解读(实测观察):

  • cron_job_schedule 两种取值:Interval(按 cron_job_interval_minutes 周期跑)与 Daily(按 cron_job_daily_at 时刻跑);
  • app_update 出厂即 enabled=0——只有当你在 Maintenance > Update 页点了 Queue Update 它才会被拉起干活;
  • cron_job_last_status 是排障第一入口:Completed 正常;Stopped: … 带原因(本实例的 mail_queue=Stopped 表示队列为空、ticket_email_parser=Stopped 是因为邮件转工单未启用,都是预期行为而非故障);
  • 表内还有 cron_job_last_run_at、cron_job_last_finish_at、cron_job_last_duration、cron_job_last_error 字段(实测 SHOW COLUMNS 可见),分别记录最近运行时刻、结束时刻、耗时与错误原文;
  • 总开关在 settings.config_enable_cron(实测出厂 0,Maintenance > Cron 页打开后为 1)——关闭时 Daily 任务的 last_status 会如实记上 Stopped: Cron: is not enabled -- Quitting..。

3.3 锁机制(为什么不能多身份混跑)

cron/includes/cron_lock.php(源码注释实读)说明了设计:同一任务不可并发两次(自动扣款、发邮件、建工单重复都是事故),锁文件名取 md5(脚本绝对路径),用 flock 而非「检测文件存在」——flock 由内核在进程退出时释放,被杀的运行不留死锁;锁文件打不开(属主/权限问题)才算真故障,会大声报错。这就解释了 FAQ Q1 的现象:锁文件属主一旦被 root 污染,www-data 的 fopen 直接 Permission denied。

四、cron/ 任务脚本逐个实测

以下回显均为 su -s /bin/bash www-data -c 'php cron/<脚本>.php' 的真实直跑输出。

4.1 mail_queue.php —— 发件队列(每分钟)

职责:把系统积压的出站邮件(工单通知、发票、密码共享等)经 SMTP 发出去。

sudo -u www-data php /var/www/html/cron/mail_queue.php

实测回显:无输出,退出码 0(队列为空时的正常表现)。

4.2 ticket_email_parser.php —— 邮件转工单(每分钟)

职责:从 IMAP 拉取客户来信,按规则建票/回票。

sudo -u www-data php /var/www/html/cron/ticket_email_parser.php

实测回显(全文):

Email Parser: Feature is not enabled - check Settings > Ticketing > Email-to-ticket parsing. See https://docs.itflow.org/ticket_email_parse  -- Quitting..

未启用该功能时每次自行跳过,属预期行为;启用入口在后台 Settings 的工单设置。

4.3 ticket_sla.php —— SLA 监控(每分钟)

职责:按 SLA 策略检查临期/超期工单并触发告警。

sudo -u www-data php /var/www/html/cron/ticket_sla.php

实测回显:无输出,退出码 0;cron_jobs 表中该任务 cron_job_last_status = Completed。

4.4 nightly_tasks.php —— 夜间维护(每日 03:00)

职责:夜间大扫除——清理、自动关闭到期工单、各类提醒、循环发票落地等(官方 cron 文档口径 "cleanup, auto-closing resolved tickets, alerts, recurring invoices, etc.")。

sudo -u www-data php /var/www/html/cron/nightly_tasks.php

实测回显:无输出,退出码 0。

4.5 domain_refresher.php —— 域名信息刷新(每日 04:00)

职责:刷新 ITFlow 台账内域名的到期日与解析/whois 信息。依赖系统安装的 whois 客户端(Ubuntu 包名即 whois,见 B 篇 4.1 节安装清单)。

sudo -u www-data php /var/www/html/cron/domain_refresher.php

实测回显:无输出,退出码 0(实例无域名台账时静默)。

4.6 certificate_refresher.php —— 证书信息刷新(每日 03:30)

职责:刷新台账内 TLS 证书的到期日、签发者、密钥位长。

sudo -u www-data php /var/www/html/cron/certificate_refresher.php

实测回显:无输出,退出码 0。

4.7 backup.php —— 计划备份(每日 02:00,出厂关闭)

职责:① 构建计划备份(任务启用时);② 处理 Web 端排队的备份请求。

sudo -u www-data php /var/www/html/cron/backup.php

实测回显:

  • 任务未启用时:Scheduled backups are switched off - built queued work only
  • 任务启用后(实测已开启):Scheduled Full Backup complete

备份包落在 uploads/backups/,并登记进 backups 表(实测回显):

backup_file_name                                                       backup_size  backup_status  backup_source
itflow_20261023-233527_full_m-gi5Kk0HsVtFbW7qhioTff0oEhjrpaW.zip       19260        Complete       Cron

⚠️ 注意:首次构建备份后 config.php 会追加备份加密密钥($config_backup_key),丢失该密钥备份即不可恢复,务必抄录保存(详见 C 篇 3.10 节)。

4.8 app_update.php —— 落地排队更新(每日 05:00,出厂关闭)

职责:执行 Web 界面 Maintenance > Update 排队的更新任务(拉代码 + 应用数据库迁移)。

sudo -u www-data php /var/www/html/cron/app_update.php

实测回显(无排队更新时):

No update queued

4.9 update_check.php —— 更新检查(每日 02:30)

职责:对 git 远端做 fetch,报告落后几个提交。远端可达时的实测回显:

0 commit(s) behind the remote

远端不可达时的实测报错(退出码 255):

PHP Fatal error:  Uncaught Exception: git fetch failed: fatal: unable to access 'https://github.com/itflow-org/itflow.git/': GnuTLS recv error (-54): Error in the pull function. in /var/www/html/cron/update_check.php:69

该任务依赖 git 出网;网络受限服务器需为 www-data 的 git 配置代理(sudo -u www-data git config --global http.proxy http://代理地址:端口)或接受每日检查失败——失败仅影响「落后提醒」,不影响业务。

五、scripts/ 运维脚本实测

5.1 setup_cli.php —— 静默安装

全新实例的无人值守安装器(与 Web 向导等价:写 config.php、导入 141 张表、建首个管理员)。完整参数与实测安装流程见 《Ubuntu 22.04 安装 ITFlow 26.10 指南》 方案 B,要点速记:

php /var/www/html/scripts/setup_cli.php --help          # 查看全部参数
php /var/www/html/scripts/setup_cli.php --host=... --username=... \
  --password=... --database=... --base-url=... --locale=en_US \
  --timezone=Asia/Shanghai --currency=USD --company-name="..." \
  --country=China --user-name=... --user-email=... --user-password=... \
  --non-interactive

--help 实测回显确认的必选参数 13 个(host/username/password/database/base-url/locale/timezone/currency/company-name/country/user-name/user-email/user-password),可选参数含 --address/--city/--state/--zip/--phone/--company-email/--website/--repo-branch,另有 --non-interactive(缺参即失败)。

5.2 update_cli.php —— 代码与数据库更新

sudo -u www-data php /var/www/html/scripts/update_cli.php --help

实测回显(全文):

Usage: php update_cli.php [--update_db]

With no options, updates the application to the latest code on the branch this
install tracks, discarding local changes to tracked files, and then applies any
outstanding database updates.

  --update_db   Apply outstanding database updates only. The application files
                are left exactly as they are - git is not run at all.

用法解读:

  • 无参数 = 完整升级:代码硬重置到 $repo_branch 最新 + 应用未落地的数据库迁移(26.10 升级说明同口径);
  • --update_db = 只补数据库迁移、完全不碰 git(适合代码已手动到位、只差 schema 的场景);
  • 属主校验是硬门槛:root 直跑实测被拒(退出码 1):
Error: This script must be run by the file owner (www-data) to proceed.
You could try sudo -u www-data php update_cli.php

5.3 restore_cli.php —— 备份恢复

php /var/www/html/scripts/restore_cli.php --help

实测回显(全文):

Usage: php scripts/restore_cli.php --file=/path/to/backup.zip [--key=KEY] [--inspect] [--yes]

  --file=PATH   The backup archive to restore. Required.
  --key=KEY     Encryption key. Defaults to $config_backup_key from config.php.
  --inspect     Show what is in the archive and exit without changing anything.
  --yes         Skip the confirmation prompt.

恢复演练第一步永远是检视(对实测生成的备份包执行 --inspect 的真实回显):

Backup archive:  itflow_20261023-233527_full_m-gi5Kk0HsVtFbW7qhioTff0oEhjrpaW.zip
Size:            18.8 KB
Type:            Full Backup
Taken:           2026-10-23 23:35:27
ITFlow version:  Unknown
Database version: 2.7.9
Contains:        db.sql, uploads.zip, version.txt
This install is at database version 2.7.9.

--inspect given, nothing was changed.

包内容 = db.sql(全库转储)+ uploads.zip(上传文件)+ version.txt(版本标记);密钥默认取 config.php 的 $config_backup_key,也可用 --key 显式给。确认无误后加 --yes 才会真正写库。

六、典型运维场景串联

把上文命令按场景串起来(全部命令在本实例实测可跑通):

  1. 晨检三连:SELECT cron_job_name, cron_job_last_status FROM cron_jobs(有无非预期 Stopped)→ SELECT config_cron_last_dispatch_at FROM settings(调度是否活着)→ sudo -u www-data php /var/www/html/cron/mail_queue.php(手动补一发邮件队列);
  2. 手动触发一次全量备份:sudo -u www-data php /var/www/html/cron/backup.php → 确认 Scheduled Full Backup complete → --inspect 检视新包 → 抄录/核对 $config_backup_key;
  3. 月度升级:先 sudo -u www-data php /var/www/html/cron/update_check.php(或 Web 端 Maintenance > Update)确认落后提交 → 备份(上一条)→ sudo -u www-data php /var/www/html/scripts/update_cli.php(代码+库一次到位)→ 再跑一次 update_check 归零、巡检 cron_jobs;
  4. 恢复演练(换环境验证备份可用):准备等版本空实例 → restore_cli.php --file=... --inspect 检视 → --yes 恢复 → 登录核验。

七、常见问题(FAQ)

Q1:手动跑过一次脚本后,系统 cron 的该任务开始报锁文件权限错误?

实录(www-data 执行时的真实报错):

PHP Warning:  fopen(/tmp/itflow_cron_696309544e04e1eb7f6819c8a312c17f.lock): Failed to open stream: Permission denied in /var/www/html/cron/includes/cron_lock.php on line 80
Cannot open the cron lock file at /tmp/itflow_cron_696309544e04e1eb7f6819c8a312c17f.lock - check permissions and open_basedir.

原因:曾以 root 直跑,锁文件(命名 = md5(脚本绝对路径),每脚本一把)属主变成 root。修复:sudo rm -f /tmp/itflow_cron_*.lock,之后只以 www-data 运行。锁文件随时可删——flock 语义下删除后下一次运行会重建。

Q2:update_check 报 git fetch failed(Permission denied: .git/FETCH_HEAD)?

实录:

PHP Fatal error:  Uncaught Exception: git fetch failed: error: cannot open .git/FETCH_HEAD: Permission denied in /var/www/html/cron/update_check.php:69

原因:root 直跑过 git 类任务,.git 内出现 root 属主文件。修复:sudo chown -R www-data:www-data /var/www/html,实测修复后恢复。治本同 Q1——统一 www-data 身份。

Q3:update_check 报 GnuTLS recv error?

实录见 4.9 节。是出网到 GitHub 的 TLS 握手故障(网络/代理问题),不是应用故障:为 www-data 的 git 配代理或放宽检查频率;该任务失败不影响其他任务(调度器逐任务隔离)。

Q4:为什么有的任务 last_status 是 Stopped 却说不是故障?

cron_jobs 的 Stopped 只表示「本次没有做事」,后缀是原因。实测样例:mail_queue 空队列 → Stopped;ticket_email_parser 未启用 → Stopped: Email Parser: Feature is not enabled...;总开关没开 → Stopped: Cron: is not enabled -- Quitting..。看后缀定性,Completed 与带预期原因的 Stopped 都属正常。

Q5:能把任务从 cron 挪到别的调度器(systemd timer)吗?

可以但没必要。cron.php 自带应用层的幂等与锁(flock + cron_jobs 记账),systemd timer 只需同样以 www-data 身份每分钟拉起 php /var/www/html/cron/cron.php 即可等价替代 /etc/cron.d 条目;任务语义仍由 Maintenance > Cron 页管理。

八、参考链接

  1. 官方 cron 文档(脚本职责表):https://docs.itflow.org/cron (查询日期 2026-10-23)
  2. 官方邮件转工单文档:https://docs.itflow.org/ticket_email_parse (查询日期 2026-10-23)
  3. 官方备份文档:https://docs.itflow.org/backups (查询日期 2026-10-23)
  4. 源码仓库(scripts/ 与 cron/ 全部脚本):https://github.com/itflow-org/itflow (v26.10 标签,查询日期 2026-10-23)
  5. 同专栏 《ITFlow 26.10 介绍与选型指南》、《Ubuntu 22.04 安装 ITFlow 26.10 指南》、《ITFlow 26.10 配置参数详解》