phpIPAM 1.8.3 常用 CLI 命令与工具详解
phpIPAM 1.8.3 自带 10 个 CLI 脚本逐个实测:pingCheck/discoveryCheck 扫描与状态翻转、clear_logs、remove_offline、reset-admin-password、crond 编排与 1.8.3 已知缺陷脚本避坑,全部真实回显。
phpIPAM 1.8.3 常用 CLI 命令与工具详解
目标:逐个讲清 phpIPAM 自带的命令行工具——
functions/scripts/下 10 个 PHP 脚本的用途、参数、真实输出,以及 crond 计划任务的编排方式,让存活扫描、主机发现、日志清理、管理员密码找回等运维操作可以纯命令行完成。已在 Ubuntu 22.04 + phpIPAM 1.8.3 + PHP 8.3.36 + MariaDB 11.8 环境逐条实测。
一、环境信息
- 操作系统:Ubuntu 22.04(x86_64)
- phpIPAM:v1.8.3(应用目录 /opt/phpipam)
- PHP:8.3.36(cli)(built: Oct 21 2026 16:38:20) (NTS)(实测
php -v) - 数据库:MariaDB 11.8.9
- fping:Version 5.5,路径 /usr/sbin/fping(实测
fping --version) - PHP 扩展(实测
php -m与扫描相关项):curl、gd、mysqlnd、PDO、pdo_mysql、snmp、sockets - 演示数据:两个已登记网段 192.168.100.0/24(演示子网,2 个地址)与 10.89.62.0/24(实验内网段,网关 10.89.62.1 可 ping 通),地址 5 条
二、工具概览
全部 CLI 工具集中在应用目录的 functions/scripts/ 下,先看清单:
ls /opt/phpipam/functions/scripts/
实测输出:
clear_logs.php
discoveryCheck.php
find_full_subnets.php
find_untranslated_files.php
merge_databases.php
pingCheck.php
remove_offline_addresses.php
reset-admin-password.php
resolveIPaddresses.php
sync_ad_groups.php
10 个脚本分工速查:
| 脚本 | 用途 | 调度建议 |
|---|---|---|
| pingCheck.php | 存活检测,刷新地址 lastSeen 与状态标签 | 每 15 分钟~1 小时 |
| discoveryCheck.php | 扫描已登记网段,发现未登记主机并自动入库 | 与 pingCheck 同频 |
| resolveIPaddresses.php | 对已登记地址做 DNS 反解,补全 hostname | 每天 1 次 |
| clear_logs.php | 清理登录/操作日志与变更历史 | 每周或按量 |
| remove_offline_addresses.php | 删除失联超过阈值的地址 | 每天 1 次 |
| find_full_subnets.php | 找出地址利用率达 100% 的网段 | 每周 |
| reset-admin-password.php | 找回/重置 Admin 密码 | 按需(交互) |
| merge_databases.php | 合并两个 phpIPAM 库(迁移场景) | 一次性 |
| sync_ad_groups.php | 同步 AD/LDAP 用户组 | 接 AD 时定时 |
| find_untranslated_files.php | 开发辅助:找未翻译文件 | 按需 |
💡 技术拓展:扫描任务的「触发方式」不止 crond 一种。常见对比——
方式 原理 适用 系统 crond 按时刻表定期执行 php 脚本 标准做法,本文主线 systemd timer 单元化定时器,依赖少、日志进 journal 现代发行版替代 crond 手工执行 运维当场跑一次验证 排障与首次配置验证 phpIPAM 官方与 Docker 镜像均采用 crond 方案(镜像内由 SCAN_INTERVAL 生成 crontab),本文按 crond 主线展开,手工执行用于验证结果。
三、前置条件
- 已完成 phpIPAM 安装并能登录(部署见《phpIPAM 1.8.3 Docker Compose 部署指南》);脚本经应用配置 config.php 连接数据库,安装正常则 CLI 可直接运行;
- 网段需开启扫描位:网段编辑页勾选 check subnet for new hosts(discoverSubnet)与/或 check subnet for status updates(pingSubnet)——未勾选时脚本直接空跑(实测报「No subnets are marked for checking status updates」或「No subnets are marked for new hosts checking」);
- 建议为 crond 准备 php 解释器绝对路径
/usr/bin/php(镜像内实测该路径存在)。
先做一次空跑验证脚本可用(未勾选扫描位时的实测输出):
php /opt/phpipam/functions/scripts/pingCheck.php
实测输出:
pingCheck: No subnets are marked for checking status updates
php /opt/phpipam/functions/scripts/discoveryCheck.php
实测输出:
discoveryCheck: No subnets are marked for new hosts checking
💡 说明:这两行空跑输出同时是「网段没开扫描位」的判据——看到它就去网段编辑页勾选对应选项。
四、各工具详解
4.1 pingCheck.php:存活检测与状态打标
对勾选了「status updates」的网段逐地址探测(默认 ping),更新 lastSeen;updateTags 开启时把不通的地址状态标签翻成 Offline。手工执行一次(两个网段、5 个地址,其中网关可 ping 通):
php /opt/phpipam/functions/scripts/pingCheck.php
实测输出:
pingCheck: Scan start, 5 IPs
pingCheck: Scan complete, 3 updates
核对效果——不可达地址的 lastSeen 被刷新为扫描时刻(原值为 1970-01-01 00:00:01 的「从未见过」地址不被触碰):
mariadb -uphpipam -pq1w2e3r4 phpipam \
-e "SELECT id, INET_NTOA(ip_addr) AS ip, state, lastSeen FROM ipaddresses WHERE subnetId IN (7,9);"
实测输出:
id ip state lastSeen
11 192.168.100.1 2 1970-01-01 00:00:01
12 192.168.100.2 2 1970-01-01 00:00:01
13 10.89.62.1 2 2026-10-22 18:19:15
14 10.89.62.3 2 2026-10-22 18:19:15
15 10.89.62.2 2 2026-10-22 18:19:15
⚠️ 注意(实测关键结论):
updateTags(Administration → phpIPAM settings)默认为 0,此阶段扫描只刷新 lastSeen、不改 state;且 v1.8.3 源码(class.Scan.php 的 update_address_tag)对 lastSeen 为1970-01-01 00:00:01等哨兵值的「从未见过」地址明确豁免,不会打 Offline 标。首次接入的地址先跑通一轮 lastSeen 再谈状态翻转。
开启 updateTags=1 后验证状态翻转——把演示地址 id=11 的 lastSeen 设为 10 分钟前(早于 pingStatus 的离线阈值 1800 秒不必,实测 5 分钟即触发),再跑一次:
mariadb -uphpipam -pq1w2e3r4 phpipam -e \
"UPDATE ipaddresses SET lastSeen='2026-10-22 18:15:00' WHERE id=11;"
php /opt/phpipam/functions/scripts/pingCheck.php
mariadb -uphpipam -pq1w2e3r4 phpipam -e \
"SELECT id, INET_NTOA(ip_addr) AS ip, state, lastSeen FROM ipaddresses WHERE id=11;"
实测输出:
pingCheck: Scan start, 5 IPs
pingCheck: Scan complete, 0 updates
id ip state lastSeen
11 192.168.100.1 1 2026-10-22 18:15:00
state 由 2(Online/Used)翻成 1(Offline),即自动打标生效。状态标签对照(ipTags 表实测值):
| state | 标签 | 颜色 | 说明 |
|---|---|---|---|
| 1 | Offline | #f59c99 | 扫描确认不通 |
| 2 | Used | #a9c9a4 | 在用(在线) |
| 3 | Reserved | #9ac0cd | 保留,不会被翻成 Offline |
| 4 | DHCP | #c9c9c9 | 动态池地址 |
第二次连续执行通常为 0 updates(状态已收敛、lastSeen 已刷新,无变化可报):
pingCheck: Scan start, 5 IPs
pingCheck: Scan complete, 0 updates
4.2 discoveryCheck.php:新主机自动发现
对勾选了「new hosts checking」的网段做存活探测,发现库中未登记的在线主机后自动入库。实测:先删掉演示地址 10.89.62.2(模拟「网内新设备未登记」),再跑发现:
mariadb -uphpipam -pq1w2e3r4 phpipam -e "DELETE FROM ipaddresses WHERE id=15;"
php /opt/phpipam/functions/scripts/discoveryCheck.php
实测输出:
discoveryCheck: Scan start, 504 IPs
discoveryCheck: Scan complete, 2 new hosts
核对入库结果:
mariadb -uphpipam -pq1w2e3r4 phpipam \
-e "SELECT id, INET_NTOA(ip_addr) AS ip, hostname, description FROM ipaddresses WHERE subnetId=9;"
实测输出:
id ip hostname description
13 10.89.62.1 gw-lab Laboratory uplink gateway
14 10.89.62.3 dns-lab Laboratory DNS server
16 10.89.62.2 phpipam-1.8.3-db.phpipam-183-stack_phpipam-net -- autodiscovered --
17 10.89.62.4 phpipam-1.8.3-cron.phpipam-183-stack_phpipam-net -- autodiscovered --
💡 说明:
/24网段全量探测是 504 个 IP(256 减去网络/广播及系统保留);新主机 description 标为-- autodiscovered --,hostname 取反解结果(无 DNS 时显示探测来源名,本实验环境展示为发出响应的主机名)。扫描周期内重复发现不会重复建记录。
4.3 resolveIPaddresses.php:DNS 反解补全
对已登记地址做 PTR 反解,把主机名写回 hostname 字段;resolve_emptyonly=true(默认,实查 config.dist.php)时只补空缺项。手工执行:
php /opt/phpipam/functions/scripts/resolveIPaddresses.php
echo "exit=$?"
实测输出(内网无 PTR 记录、且无空缺可补时静默通过):
exit=0
💡 说明:脚本无输出不代表失败——没有需要反解的地址或 DNS 无记录时保持静默,退出码 0 即成功;
resolve_verbose=true时有更新会打印明细。给网段勾选 resolveDNS 或配好 nameserver 后,在有 PTR 的网段上执行可见 hostname 被自动补全。
4.4 clear_logs.php:清理日志与变更历史
清理登录/操作日志与 changelog(settings 表 enableChangelog=1 时积累的变更记录)。实测:
php /opt/phpipam/functions/scripts/clear_logs.php
实测输出:
Logs cleared successfully!
Changelogs cleared successfully!
4.5 remove_offline_addresses.php:删除失联地址
删除失联超过 $config['removed_addresses_timelimit'](默认 7 天,config.dist.php 实测值)的地址,发信开关 $config['removed_addresses_send_mail']。实测(当前无失联满 7 天的地址):
php /opt/phpipam/functions/scripts/remove_offline_addresses.php
实测输出:
Looking for addresses offline since 2026-10-15 18:21:29. Found 0.
⚠️ 注意:未在 config.php 定义
removed_addresses_timelimit时脚本直接拒绝运行(实测第 28 行校验):Please set timelimit for address removal!
4.6 find_full_subnets.php:找出已满网段
扫描全部网段,输出地址利用率 100% 的网段清单(供扩容规划)。实测(演示库无满网段):
php /opt/phpipam/functions/scripts/find_full_subnets.php
echo "exit=$?"
实测输出(无满网段时静默,退出码 0):
exit=0
4.7 reset-admin-password.php:重置管理员密码
Admin 密码遗失时的官方找回通道(官方 README 明示用法)。不带参数运行进入提示/交互(readline):
php /opt/phpipam/functions/scripts/reset-admin-password.php
实测输出:
Password must be at least 8 characters long
带参数直接重置(密码 ≥8 位):
php /opt/phpipam/functions/scripts/reset-admin-password.php q1w2e3r4
实测输出:
Admin password updated
sendmail: can't connect to remote host (127.0.0.1): Connection refused
⚠️ 注意:第二行的 sendmail 报错出现在未配置本地 MTA(如 postfix)的服务器上——脚本会尝试给 siteAdminMail 发通知信;密码更新本身已成功。用新密码登录验证(实测登录接口回显):
<div class='alert alert-success'>Login successful</div>
4.8 merge_databases.php:合并两个 phpIPAM 库
多套 phpIPAM 合一的迁移工具,命令行交互式执行。数据库不可达时的实测报错(用于识别环境问题):
php /opt/phpipam/functions/scripts/merge_databases.php
实测输出(节选,数据库 socket 不可达场景):
PHP Fatal error: Uncaught Exception: Could not connect to database! SQLSTATE[HY000] [2002] No such file or directory in /phpipam/functions/classes/class.PDO.php:249
Stack trace:
#0 /phpipam/functions/classes/class.PDO.php(1224): DB->connect()
#1 /phpipam/functions/classes/class.PDO.php(506): Database_PDO->connect()
⚠️ 注意:该脚本是重量级操作(跨库搬运地址/网段并处理冲突),务必先对两库做 mariadb-dump 备份、在维护窗口执行;正常执行需保证 config.php 指向的数据库可达。
4.9 sync_ad_groups.php 与 find_untranslated_files.php(1.8.3 已知缺陷)
两个脚本在 v1.8.3 独立运行即报致命错误(实测),列出供避坑:
php /opt/phpipam/functions/scripts/sync_ad_groups.php
实测输出(节选):
PHP Fatal error: Uncaught Error: Class "AD_user_sync" not found in /phpipam/functions/scripts/sync_ad_groups.php:19
Stack trace:
#0 {main}
thrown in /phpipam/functions/scripts/sync_ad_groups.php on line 19
php /opt/phpipam/functions/scripts/find_untranslated_files.php
实测输出(节选):
PHP Fatal error: Call to undefined function pf_explode() in /phpipam/functions/scripts/find_untranslated_files.php:14
Stack trace:
#0 {main}
thrown in /phpipam/functions/scripts/find_untranslated_files.php on line 14
结论:AD 组同步改走 Web 界面(Administration → Groups → AD/LDAP),1.8.3 修复前不要把这两个脚本排入计划任务;升级更高修订版后先手工试跑再上线。
4.10 crond 计划任务编排
三个扫描脚本的标准调度(每行一个任务,注释独立成行)。编辑 root 的 crontab:
crontab -e
写入(周期按需调整,两行注释说明用途):
# 新主机发现:每 30 分钟
*/30 * * * * /usr/bin/php /opt/phpipam/functions/scripts/discoveryCheck.php
# 存活检测:每 30 分钟
*/30 * * * * /usr/bin/php /opt/phpipam/functions/scripts/pingCheck.php
# DNS 反解:每天 05:10
10 5 * * * /usr/bin/php /opt/phpipam/functions/scripts/resolveIPaddresses.php
# 日志清理:每周六 03:00
0 3 * * 6 /usr/bin/php /opt/phpipam/functions/scripts/clear_logs.php
# 失联地址删除:每天 05:30
30 5 * * * /usr/bin/php /opt/phpipam/functions/scripts/remove_offline_addresses.php
重载与核对:
crontab -l | grep phpipam
实测输出(按上面录入后):
*/30 * * * * /usr/bin/php /opt/phpipam/functions/scripts/discoveryCheck.php
*/30 * * * * /usr/bin/php /opt/phpipam/functions/scripts/pingCheck.php
10 5 * * * /usr/bin/php /opt/phpipam/functions/scripts/resolveIPaddresses.php
0 3 * * 6 /usr/bin/php /opt/phpipam/functions/scripts/clear_logs.php
30 5 * * * /usr/bin/php /opt/phpipam/functions/scripts/remove_offline_addresses.php
💡 说明:官方 Docker 镜像(cron 角色)就是按
SCAN_INTERVAL生成同样的三行计划任务(discoveryCheck/pingCheck/resolveIPaddresses,实查镜像内 /start_crond),取值 5m/10m/15m/30m/1h/2h/4h/6h/12h、默认 1h;裸机部署自行按上表录入即可对齐。
五、注意事项
- 扫描位优先:pingCheck/discoveryCheck 空跑输出「No subnets are marked for checking status updates」(或 new hosts checking 同款提示)时,先到网段编辑页勾选 status updates / new hosts(实测判据,见第三章);
- updateTags 默认关闭:v1.8.3 实测默认 0,想要自动 Offline/Online 打标需在 Administration → phpIPAM settings 打开,且「从未见过」(lastSeen=1970-01-01 00:00:01)的地址不参与翻转(源码豁免,实测验证);
- 探测器路径要核对:settings 里
scanFPingPath默认 /bin/fping,而常见发行版 fping 实际装在 /usr/sbin/fping(实测 5.5 版如此),路径不符时 fping 探测会失败,改界面参数或建软链二选一; - 删除类脚本先备份:remove_offline_addresses.php 会真实删数据、merge_databases.php 会改写两库——执行前一律 mariadb-dump(用法见部署篇备份一节);
- 邮件通知依赖 MTA:三个 *_send_mail 默认 true,无本地邮件服务时会像 reset-admin-password 实测那样报 sendmail 连接拒绝(不影响主流程);不需要邮件就显式设 false;
- 脚本与 Web 共用配置:脚本读 /opt/phpipam/config.php 连库,改库连接参数后 CLI 与 Web 同时生效,无需重启。
六、常见问题(FAQ)
Q1:手工跑脚本报 No such file or directory(指向 class.PDO.php)?
config.php 的数据库地址不可达(实测 4.8 的 SQLSTATE[HY000] [2002])。核对 $db['host'] 与端口,应用与库同机时用 127.0.0.1/localhost 走 socket。
Q2:扫描输出 Scan start, N IPs 但从未有 updates?
依次核对:网段是否勾选 status updates;updateTags 是否开启(默认 0 只刷 lastSeen);探测目标是否真的可达(在服务器上手工 ping 一次验证);fping 场景核对 scanFPingPath 路径。
Q3:discoveryCheck 把不该登记的地址(打印机/哑终端)入库了?
发现的地址带 -- autodiscovered -- 描述,可在网段上关闭 new hosts checking,或对不需要发现的范围改用更小掩码的子网登记。
Q4:cron 排了任务但没效果?
用绝对路径的 php(/usr/bin/php);手工以同一命令验证(本章各脚本均给出实测);再查 cron 日志(Ubuntu 下 /var/log/syslog 中 CRON 行)确认被调度。
Q5:reset-admin-password 报密码太短?
密码必须 ≥8 字符(实测无参数时直接提示 Password must be at least 8 characters long);不带参数则进入 readline 交互输入。
七、参考链接
- 官方脚本目录(v1.8.3):https://github.com/phpipam/phpipam/tree/v1.8.3/functions/scripts
- 官方 README(Admin 密码找回一节):https://github.com/phpipam/phpipam#i-forgot-my-admin-password
- 官方安装与升级文档:https://phpipam.net/documents/installation/
- 本站相关文档:《phpIPAM 1.8.3 介绍与选型指南》(认知与选型)、《phpIPAM 1.8.3 Docker Compose 部署指南》(部署与备份)、《phpIPAM 1.8.3 配置参数详解》(扫描参数与 updateTags)