phpIPAM 1.8.3 常用 CLI 命令与工具详解

phpIPAM 1.8.3 自带 10 个 CLI 脚本逐个实测:pingCheck/discoveryCheck 扫描与状态翻转、clear_logs、remove_offline、reset-admin-password、crond 编排与 1.8.3 已知缺陷脚本避坑,全部真实回显。

phpIPAMphpIPAMPHPMySQLIPAM2026/10/22

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 主线展开,手工执行用于验证结果。

三、前置条件

  1. 已完成 phpIPAM 安装并能登录(部署见《phpIPAM 1.8.3 Docker Compose 部署指南》);脚本经应用配置 config.php 连接数据库,安装正常则 CLI 可直接运行;
  2. 网段需开启扫描位:网段编辑页勾选 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」);
  3. 建议为 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标签颜色说明
1Offline#f59c99扫描确认不通
2Used#a9c9a4在用(在线)
3Reserved#9ac0cd保留,不会被翻成 Offline
4DHCP#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;裸机部署自行按上表录入即可对齐。

五、注意事项

  1. 扫描位优先:pingCheck/discoveryCheck 空跑输出「No subnets are marked for checking status updates」(或 new hosts checking 同款提示)时,先到网段编辑页勾选 status updates / new hosts(实测判据,见第三章);
  2. updateTags 默认关闭:v1.8.3 实测默认 0,想要自动 Offline/Online 打标需在 Administration → phpIPAM settings 打开,且「从未见过」(lastSeen=1970-01-01 00:00:01)的地址不参与翻转(源码豁免,实测验证);
  3. 探测器路径要核对:settings 里 scanFPingPath 默认 /bin/fping,而常见发行版 fping 实际装在 /usr/sbin/fping(实测 5.5 版如此),路径不符时 fping 探测会失败,改界面参数或建软链二选一;
  4. 删除类脚本先备份:remove_offline_addresses.php 会真实删数据、merge_databases.php 会改写两库——执行前一律 mariadb-dump(用法见部署篇备份一节);
  5. 邮件通知依赖 MTA:三个 *_send_mail 默认 true,无本地邮件服务时会像 reset-admin-password 实测那样报 sendmail 连接拒绝(不影响主流程);不需要邮件就显式设 false;
  6. 脚本与 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 交互输入。

七、参考链接