news 2026/10/23 14:01:55

PacketFence full-import:在 devel 分支上准备与测试全量导出/导入机制

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
PacketFence full-import:在 devel 分支上准备与测试全量导出/导入机制
  • 网络安全
  • 认证鉴权
  • 后端

【免费下载链接】packetfence

PacketFence is a fully supported, trusted, Free and Open Source network access control (NAC) solution. Boasting an impressive feature set including a captive-portal for registration and remediation, centralized wired and wireless management, powerful BYOD management options, 802.1X support, layer-2 isolation of problematic devices; PacketFence can be used to effectively secure networks small to very large heterogeneous networks.

项目地址:https://gitcode.com/gh_mirrors/pa/packetfence
点击查看免费下载

PacketFence 的full-import模块(位于 addons/full-import)实现了“一键导出 + 一键导入”的整机迁移与版本升级机制,其开发验证的第一步就是在 devel 分支上把占位的数据库 Schema 与升级脚本重命名为真实的版本号文件,再运行 import.sh 完成从旧版本导出包到新版本的数据库、配置全量恢复。本文围绕 addons/full-import/README.md 中给出的 devel 环境准备指令展开,结合仓库中 database.functions、helpers.functions、configuration.functions 的源码实现,讲清 X.Y 占位文件机制、导入脚本的完整调用链,以及配套的 export.sh 导出侧细节与集成测试用例,帮助你在开发分支上正确搭建并验证整个导入/导出流程。

1. 文档定位:full-import 是什么、devel 测试要解决什么问题

addons/full-import/README.md 本身是一份面向开发者的简短操作说明,标题为 “Instructions to test import against devel branch”,核心内容只有两条命令:

# Replace 11.0 with the current devel version cp db/pf-schema-X.Y.sql db/pf-schema-11.0.sql
# Replace 10.3-11.0 with the current stable and current devel version cp db/upgrade-X.X-X.Y.sql db/upgrade-10.3-11.0.sql

这两条命令解决的是:导入脚本在跨版本恢复时会按版本号在/usr/local/pf/db/下查找pf-schema-<版本>.sql与upgrade-<旧版本>-<新版本>.sql,而 devel 分支发布包中这两个文件只以pf-schema-X.Y.sql、upgrade-X.X-X.Y.sql的占位形态存在。测试 devel 上的 import 之前,必须先把占位文件复制成与当前版本号匹配的文件名,否则版本探测与数据库升级链路会找不到目标文件。

仓库当前 devel 版本为 16.0.0(见 conf/pf-release:PacketFence 16.0.0),因此按文档要求把11.0、10.3-11.0替换为当前稳定版与当前 devel 版本后,实际操作等价于:

cp db/pf-schema-X.Y.sql db/pf-schema-16.0.sql cp db/upgrade-X.X-X.Y.sql db/upgrade-15.2-16.0.sql

其中 db/upgrade-X.X-X.Y.sql 当前内容正是 15.2 → 16.0 的升级脚本(脚本头部SET @MAJOR_VERSION = 16; SET @MINOR_VERSION = 0;与PREV 15.2)。官方完整的导出/导入机制说明见 docs/installation/export_import_mechanism.asciidoc,其中明确了适用前提:导出支持 10.3 以上任意版本;从 10.3 导出的数据可导入 11.0 之后的任意版本(若数据库备份使用 mariadb-backup 则不受该限制影响);导入必须在单机服务器上执行,不建议直接恢复到集群。

full-import目录的完整构成如下,本文后续会逐一对照源码展开:

文件职责
README.mddevel 分支导入测试前的环境准备(本文核心)
export.sh在源机器上组装可导出的 tgz 归档
import.sh在目标机器上恢复数据库与配置
find-extra-files.pl扫描配置中被引用的“额外文件”清单
Makefile构建packetfence-export包时的安装规则

2. 为什么需要复制占位文件:源码中的版本探测链路

README 中两条cp命令对应导入流程中两条独立的版本依赖,理解这两条链路才能解释“为什么要提前复制”。

2.1 数据库升级链路:upgrade_database依赖upgrade-*.sql文件名

导入主流程在 import.sh 的 import_db 中处理完数据库还原后,若非--restore-as-is,会先调用handle_devel_upgrade再调用upgrade_database。handle_devel_upgrade定义在 helpers.functions#L80-L90:

function handle_devel_upgrade() { UPGRADE_TO="$1" if [ -f /usr/local/pf/db/upgrade-X.X-X.Y.sql ]; then ... echo -n "You need to input the PF version that comes before $UPGRADE_TO. ... " read UPGRADING_FROM cp /usr/local/pf/db/upgrade-X.X-X.Y.sql /usr/local/pf/db/upgrade-$UPGRADING_FROM-$UPGRADE_TO.sql fi }

也就是说,在安装介质里检测到upgrade-X.X-X.Y.sql时,脚本会交互式地要求操作者输入“旧版本号”(例如 15.2),然后自己把占位文件复制为upgrade-15.2-16.0.sql。而 README 面向 devel 分支开发者给出的cp db/upgrade-X.X-X.Y.sql db/upgrade-10.3-11.0.sql,本质上是在源码树中预先完成同样的改名,使后续的脚本匹配逻辑能直接命中。

随后的upgrade_database(database.functions#L198-L230)从数据库中读取当前版本并选择升级脚本:

db_version=`mysql ${mariadb_args} $db_name -e "select version from pf_version order by id desc limit 1;" | egrep -o '^[0-9]+\.[0-9]+'` scripts=`get_db_upgrade_scripts $db_version`

get_db_upgrade_scripts(database.functions#L182-L188)通过ls /usr/local/pf/db/upgrade-* | egrep ... | sort --version-sort | sed -ne ...列出所有形如upgrade-X.X-X.Y.sql或upgrade-X.X.X-X.Y.Z.sql的文件,按版本号排序后只取“起点版本之后”的所有脚本逐个执行;最后还会truncate keyed清空 keyed 表以强制失效缓存。注意脚本匹配的是文件名中的版本号,这就是为什么占位文件upgrade-X.X-X.Y.sql不参与匹配——必须先复制成真实版本号文件。

2.2 无触发器导出包的 Schema 兜底:pf-schema-X.Y.sql

第二条cp命令针对的是另一条兜底路径。当导出包中的 mysqldump 不包含触发器、且包内也没有triggers.sql(旧版导出)时,import_mysqldump会从 Schema 文件中抽取触发器定义重新应用,其文件选择逻辑在 database.functions#L91-L100 与 L105-L119:

schema_version=`echo "$pf_version_in_export" | egrep -o '^[0-9]+\.[0-9]+'` schema_file="/usr/local/pf/db/pf-schema-$schema_version.sql" [ -f "$schema_file" ] || schema_file="/usr/local/pf/db/pf-schema-X.Y.sql"

可以看到,目标版本(即 devel 版本)的pf-schema-<major>.<minor>.sql缺失时会回退到pf-schema-X.Y.sql。README 中第一条cp db/pf-schema-X.Y.sql db/pf-schema-11.0.sql正是保证 devel 版本号文件也存在,避免回退;同样的兜底逻辑还出现在 handle_devel_db_schema 中:若/usr/local/pf/db/pf-schema-$restoring_version.sql不存在,会自动cp /usr/local/pf/db/pf-schema-X.Y.sql过去并打印提示。

两条命令合起来保证了:在 devel 分支的介质上,import.sh的“版本探测 → 数据库升级 → 触发器/表结构兜底”三段逻辑都能按版本号正常命中文件,这也是 devel 集成测试(见第 6 节)能够跑通的前提。

3. 导入侧完整流程:import.sh 如何消费 devel 环境

README 只讲了测试前的两步准备,真正被验证的对象是 import.sh。按源码结构,整个导入分为四个阶段:prepare_import→import_db/import_config→finalize_import。

3.1 参数解析与模式

import.sh#L203-L273 使用getopt解析参数,官方 help 文本(import.sh#L185-L201)与各开关对应的内部变量如下:

选项作用内部变量
-f, --file <archive>指定导出归档路径(必填)EXPORT_FILE
--db只导入数据库do_db_import=1
--conf只导入配置do_config_import=0/1
--skip-adjust-db-conf配置导入时保留备份中的数据库 host/port,不强制改为 localhostdo_adjust_db_conf=0
--restore-as-is按原样恢复:不做数据库/配置升级、不改 host/port、全程无交互(要求同版本)do_restore_as_is=1(并隐含do_adjust_db_conf=0)
--update-cluster-conf恢复导出包中的cluster.conf并按本机调整do_update_cluster_conf=1

不带任何选项时执行完整导入(do_full_import=1),即 import.sh#L280-L287 中1) import_db ; import_config的分支。

3.2 prepare_import:解包与服务停止

prepare_import(import.sh#L17-L75) 依次完成:

  1. 校验归档存在,mktemp -d建临时目录并trap cleanup EXIT;
  2. tar -xf export.tgz解出归档内容(内含packetfence-conf-*/ 旧版的packetfence-files-*配置包,以及packetfence-db-dump-*数据库包);
  3. 解包配置包到$extract_dir/usr/local/pf,并修复 13.1 之前版本的路径问题(usr/local/pf/usr/local/pf双层目录展平,见 import.sh#L50-L55);
  4. 对.gz压缩的数据库包执行gunzip;
  5. 通过get_pf_version_in_export(configuration.functions#L387-L390)从导出包内usr/local/pf/conf/pf-release读取源端版本——第 2 节的 Schema 兜底逻辑正是用这个版本号;
  6. 停止服务:如存在 monit 则先systemctl stop monit并 disable,然后systemctl isolate packetfence-base与systemctl stop packetfence-galera-autofix。

3.3 import_db:双格式数据库恢复 + devel 升级

import_db(import.sh#L77-L112) 依据数据库包后缀分流:

  • .sql(mysqldump 路径):调用 import_mysqldump。该函数先处理沙箱模式首行注释(M!999999),重建目标库(DEFAULT CHARACTER SET = 'utf8mb4');若检测到 dump 中无CREATE TRIGGER(以 pf 普通用户导出、无 TRIGGER 权限的典型形态),则把DROP TABLE IF EXISTS注释化、CREATE TABLE改为CREATE TABLE IF NOT EXISTS、INSERT改为INSERT IGNORE,并删除两个已废弃表的DELETE IGNORE语句;随后若归档带有新版导出的triggers.sql/excluded_tables_schema.sql则应用,否则从pf-schema-<版本>.sql(缺失时回退pf-schema-X.Y.sql)中用awk抽取触发器与locationlog_history、iplog_archive表结构重建——这正是 README 第二条准备的 Schema 文件的消费点;最后导入grants.sql恢复授权。
  • .xbstream(mariabackup 路径):调用 import_mariabackup。它会按源端版本安装对应 mariabackup(10.3.0 用历史固定 deb/rpm,其余用当前发行版包,见 install_mariabackup),mbstream -x解包、mariabackup --prepare应用 InnoDB 日志,停止packetfence-mariadb后把/var/lib/mysql改名备份、--move-back --force-non-empty-directories回迁数据并chown -R mysql:,再启动数据库;非--restore-as-is模式下执行mysql_upgrade -p(注意提示输入的是源服务器的 root 密码)。导入成功后cleanup会卸载临时安装的 mariabackup(import.sh#L9-L15),这也是官方文档特别提醒“若导入前已装 mariabackup,需确认导入结束后它仍在”的原因。

两条路径完成后,回到import_db尾部:--restore-as-is直接跳过升级;否则handle_devel_upgrade拿到目标版本(从本机/usr/local/pf/conf/pf-release用egrep -o '[0-9]+\.[0-9]+\.[0-9]+$'截取的 major.minor,import.sh#L103)触发 2.1 节的占位改名,然后upgrade_database $db_name按版本序列执行全部upgrade-*.sql。源码中另有一条注释表明设计边界:#TODO: check the version of the export, we want to support only 10.3.0 and above(import.sh#L105),与文档“export supported above 10.3”的表述一致。

3.4 import_config:配置恢复与网络/集群适配

import_config(import.sh#L114-L145) 依次调用(均位于 configuration.functions):

  1. restore_config_files:按@pf::file_paths::stored_config_files(lib/pf/file_paths.pm#L416-L447,涵盖pf.conf、networks.conf、profiles.conf、vlan_filters.conf.defaults、cluster.conf等 30 余个文件)加上pfconfig.conf与add_files.txt中的额外文件逐一cp -a回本机并chown pf:;cluster.conf被显式跳过,交由第 3 步处理;
  2. handle_network_change:遍历pf.conf的[interface xxx]段,接口在本机存在且 IP 与配置不一致时,交互式询问是改写pf.conf(rewrite_pf_ip_address会连带改写 networks.conf 中同网段网关/DNS 与路由引用)、改名还是删除该段;接口不存在时列出ip a show编号列表供选择替换。--restore-as-is模式下这些交互被整体跳过(helpers.functions 的 prompt 对该模式恒返回 n);
  3. handle_cluster_conf_restore:默认把导出包的cluster.conf存为/usr/local/pf/conf/cluster.conf.imported供参考,本机cluster.conf重置为空(单机态);--update-cluster-conf时恢复导出副本并通过handle_cluster_conf_change同步本机节点段的接口 IP 与 management_ip、传播接口改名到[CLUSTER]VIP 段(VIP 与对等节点段保持原值,文档明确要求导入后人工复核);
  4. restore_profile_templates:整目录恢复/usr/local/pf/html/captive-portal/profile-templates;
  5. upgrade_imported_configuration:从导出包pf-release取源端版本,versions_since(helpers.functions#L47-L54)列出该版本之后的全部 minor 版本,逐个匹配/usr/local/pf/addons/upgrade/to-<版本>-*的配置升级脚本依次执行(devel 版本同样依赖第 2 节准备好的版本号文件才能被ls /usr/local/pf/db/upgrade-*与versions_since的排序逻辑正确覆盖);
  6. adjust_configuration(除非--skip-adjust-db-conf):把 pfconfig.conf 的[mysql] host与pf.conf的[database] host改回localhost,并删除显式 port;
  7. restore_certificates:恢复conf/ssl/*与raddb/certs/*。

3.5 finalize_import:收尾

finalize_import(import.sh#L148-L183) 执行pfcmd fixpermissions,重启packetfence-redis-cache与packetfence-config,调用configreload(helpers.functions#L68-L78,首次失败会等待 10 秒自动重试pfcmd configreload hard),按模式打印完成提示(如 “Completed import of the database and the configuration! Complete any necessary adjustments and restart PacketFence”),重新启用 monit(若原先存在)并清理临时目录。导入完成后仍需按 升级指南 重启 PacketFence 服务。

4. 导出侧:export.sh 与 find-extra-files.pl

导入的输入来自源端的导出归档,理解导出构成可以解释 import 侧看到的每一类文件。export.sh 的执行步骤:

  1. 在/root/backup下用find -printf "%T@ %p" | sort -n | tail -1找到最新的packetfence-db-dump-*与packetfence-conf-dump-*(export.sh#L18-L32)。这些文件由每日 00:30 的 crontab 任务 addons/exportable-backup.sh(见 debian/packetfence.cron.d#L6)产生,后者先调用 backup-and-maintenance.sh 生成数据库/配置备份(mysqldump 分支使用--skip-triggers并--ignore-table跳过locationlog_history、iplog_archive两张大历史表,原因与 import 侧的兜底重建一一对应),再调用export.sh打包;
  2. 若数据库包是*.sql.gz(mysqldump 形态),追加导出三份辅助文件:grants.sql(逐用户SHOW GRANTS展开)、triggers.sql(root 权限--triggers单表结构导出)、excluded_tables_schema.sql(被--ignore-table排除表的结构,注释明确要求与 backup-and-maintenance.sh 中的排除列表保持同步);
  3. 通过perl -Mpf::file_paths打印@stored_config_files清单写入stored_config_files.txt,再运行 find-extra-files.pl 计算“配置中引用的额外文件”:
    • 遍历每个受管配置文件,用Config::IniFiles逐段扫描参数名以_file/_path结尾(或名为file、path)且文件实际存在的参数值,把文件路径加入清单;oui_file、allowed_device_oui_file、log_config_file等固定文件被%ignored表排除,authentication.conf 的authorize_path/access_token_path与pf.conf的image_path被%ignored_params排除;
    • logo参数做路径归一:/common/...映射到/usr/local/pf/html/...,/content/...映射到/usr/local/pf/html/captive-portal/...;
    • 追加固定导出清单@extra_files_to_export:fingerbank 配置、iptables-custom.conf.inc/ip6tables 自定义段、report 配置、system init key、unified API 系统口令文件、network_behavior_policies 配置;
  4. export.sh再把额外文件中位于/usr/local/pf/之外的复制到构建目录(保留绝对路径结构),最后tar -cvzf $output *生成归档(export.sh#L111-L114)。

因此一个标准导出包至少包含:packetfence-db-dump-*.sql.gz(或.xbstream.gz)、packetfence-conf-dump-*.tgz,mysqldump 形态下另含grants.sql、triggers.sql、excluded_tables_schema.sql、stored_config_files.txt、add_files.txt及配置引用文件——与prepare_import打印的归档内容清单完全对应。

5. 在 devel 分支上的推荐测试路径

结合 README 与仓库现状,一次完整的 devel 导入验证可概括为:

# 1) devel 环境准备(README 原文,版本号替换为当前分支) cp db/pf-schema-X.Y.sql db/pf-schema-16.0.sql cp db/upgrade-X.X-X.Y.sql db/upgrade-15.2-16.0.sql # 2) 源端(旧版本安装)生成导出归档 /usr/local/pf/addons/exportable-backup.sh -f /tmp/export.tgz # 或仅重新打包已有 /root/backup 中的最新 dump: /usr/local/pf/addons/full-import/export.sh /tmp/export.tgz # 3) 目标端(16.0 全新单机安装)执行导入 /usr/local/pf/addons/full-import/import.sh -f /tmp/export.tgz

仓库中的 Venom 集成测试 t/venom/test_suites/import/import.yml 展示了 CI 中的真实用法:先从pfdeb9stable虚机scp一个现成的export.tgz,再在 devel 目标机上执行export.sh/导入流程(断言部分在源码中标注为## FIXME)。t/venom/test_suites/backup_db_and_restore 与 docs/cluster/layer_3_clusters.asciidoc 中还使用了import.sh --db -f /root/backup/packetfence-exportable-backup-...tgz这类只恢复数据库的调用形态,验证--db分支。

6. 适用前提与限制

  • 单机导入:导入过程会在prepare_import阶段 isolate 服务并可能重命名/var/lib/mysql,官方文档明确恢复到集群不受支持;恢复完成后可按 集群指南 重建集群,--update-cluster-conf只适配本地节点段,VIP 与对等节点段必须人工复核。
  • 全新安装优先:文档建议在干净安装上导入;在已有实例上导入“结果可能不同”。
  • 网络配置不改物理网卡:导入只更新 PacketFence 的 IP 配置(pf.conf/networks.conf),建议导入前先把目标 IP 配到网卡上;也不会自动重新加入 AD 域。
  • 恢复范围:恢复对象是@pf::file_paths::stored_config_files清单内的配置文件、若干非.conf数据文件(oui.txt等)、*.conf.defaults、find-extra-files.pl自动发现的引用文件、profile 模板与标准证书;不恢复/usr/local/pf/conf/radiusd/*、/usr/local/pf/conf/log.conf.d/*、iptables.conf.tt等,需手工迁移。由于*.conf.defaults按原样覆盖,跨版本导入后应复核默认文件。
  • mariabackup 注意事项:导入脚本会按需临时安装/卸载 mariabackup;10.3.0 源端使用固定历史版本包。若环境原本已装 mariabackup,导入结束后需确认其仍可用。
  • 失败处理:官方建议导入出现异常时直接重跑脚本——mysqldump 路径上的IF NOT EXISTS/INSERT IGNORE改写与触发器重放都是幂等的,这也是 2.1/2.2 节链路设计为可重复执行的原因。

7. 小结

addons/full-import/README.md 的两行cp命令看似简单,实则是 devel 分支上打通整个导入/导出机制的钥匙:它让import.sh的版本探测(get_db_upgrade_scripts、versions_since)与 Schema 兜底(pf-schema-X.Y.sql回退)都能在按版本号命名的文件中命中目标。掌握“占位文件 → 版本号文件”的改名规则后,再对照本文第 3、4 节梳理的prepare_import/import_db/import_config/finalize_import调用链与export.sh的打包构成,就可以在当前仓库(devel 16.0.0)上独立完成一次从 15.2 到 16.0 的全量导入验证,并正确区分--restore-as-is、--update-cluster-conf、--skip-adjust-db-conf等开关在集群与跨库场景下的行为差异。

  • 网络安全
  • 认证鉴权
  • 后端

【免费下载链接】packetfence

PacketFence is a fully supported, trusted, Free and Open Source network access control (NAC) solution. Boasting an impressive feature set including a captive-portal for registration and remediation, centralized wired and wireless management, powerful BYOD management options, 802.1X support, layer-2 isolation of problematic devices; PacketFence can be used to effectively secure networks small to very large heterogeneous networks.

项目地址:https://gitcode.com/gh_mirrors/pa/packetfence
点击查看免费下载

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/22 15:29:21

OceanBase 2.2数据库性能测试实战:JMeter分布式事务压测指南

1. 项目概述&#xff1a;为什么一个数据库性能测试值得专门写一篇实操笔记&#xff1f;OceanBase 2.2 这个版本在业内有个很实在的标签——“从金融核心场景反向锤炼出来的稳定器”。它不是靠参数堆出来的纸面性能&#xff0c;而是被某大型支付平台的真实交易洪峰反复冲刷过、在…

作者头像 李华
网站建设 2026/10/18 9:30:42

gifsicle预构建检测失败的根因与工程化解决方案

1. 项目概述&#xff1a;当构建流程在 gifsicle 上突然卡住“‼ gifsicle pre-build test failed”——这个报错信息&#xff0c;我第一次在 CI/CD 流水线里看到时&#xff0c;正赶在凌晨两点打包一个即将上线的营销活动页。页面里嵌了 7 个动态加载的 GIF 图片&#xff0c;用的…

作者头像 李华
网站建设 2026/10/19 6:57:22

ROC曲线与AUC:模型排序能力的诊断听诊器

1. 这不是数学考试&#xff0c;是模型诊断的听诊器你刚跑完一个二分类模型&#xff0c;训练集准确率98%&#xff0c;测试集也到了92%——看起来很美。但上线后业务方打来电话&#xff1a;“为什么把30%的高风险客户标成了低风险&#xff1f;漏掉的这批人&#xff0c;坏账率直接…

作者头像 李华