☰
无网工控机离线部署实战:PyQt + OpenVINO + 工业相机 SDK 打进一个 tar 包
2026/10/8 2:01:13 网站建设 项目流程

无网工控机离线部署实战:PyQt + OpenVINO + 工业相机 SDK 打进一个 tar 包

场景:产线工控机(Intel N3350 双核小主机)——没网、不能装编译器、系统不能乱动。我们要把一套 PyQt5 + OpenVINO + FLIR Spinnaker 相机 SDK 的检测软件部署上去。方案:在联网的开发机上把整个可运行环境打成一个 tar 包,目标机只做两件事——解压、跑 install.sh。

工控机部署的三大约束

  1. 完全离线:pip install、apt install全部不可用,任何"到目标机上再装"的思路都行不通;
  2. CPU 弱且指令集受限:N3350 只有 SSE4.2、没有 AVX2——这直接决定了 OpenVINO 能跑但跑不快(我们实测推理 300~500ms 的元凶就是它),选型时必须先知先觉;
  3. 系统是生产环境:不能为了装你的软件把系统搞坏,安装过程必须只增不删、可回退。

第三条最重要,也最容易被忽视——后面安装脚本的设计全是围绕它。

总体思路:把"环境"当货物打包

离线部署的本质:把联网机器上"能跑的状态"原样搬运。我们的 tar 包内容:

offline_package/ ├── *.py, config.json, models/, fonts/ # 代码、模型、字体 ├── venv/ # 预装好的 Python 虚拟环境(含全部 pip 依赖) ├── spinnaker_debs/ # 相机 SDK 官方 deb 包(首选安装方式) ├── spinnaker_sdk/ # SDK 目录 + udev 规则 + 环境变量(fallback) ├── system_packages/ # 全部系统依赖 .deb(递归收集) ├── install.sh # 一键安装 └── autostart.sh # 开机自启

打包脚本的四个关键动作

1. 预建虚拟环境(--copies是重点)

python3-mvenv--copies"$OUTPUT_DIR/venv""$OUTPUT_DIR/venv/bin/pip"install-rrequirements.txt

在打包机上建好 venv 并装完所有 pip 依赖,目标机零安装。--copies用实体文件代替符号链接——默认 venv 的 python 二进制是指向系统解释的链接,拷到目标机路径一变就失效。

2. PySpin 手动拷进 site-packages

FLIR 的 Python 绑定不在 PyPI 上,只能从官方安装器装到系统 Python。所以手动把三个文件拷进 venv:

cp"$PYSPIN_SRC/PySpin.py""$VENV_SITE_PKG/"cp"$PYSPIN_SRC/_PySpin.cpython-310-x86_64-linux-gnu.so""$VENV_SITE_PKG/"

注意.so文件名带 Python 版本和架构(cpython-310-x86_64)——打包机和目标机的 Python 版本、系统架构必须一致,这是整套方案成立的前提。

3. 系统依赖递归收集

肉眼列依赖清单一定漏,用 apt 自己算:

# 把 Spinnaker SDK 和 FFmpeg 的所有递归依赖展开成清单mapfile-tDEPS<<(apt-cachedepends--recurse--no-recommends\libspinnaker libspinnaker-c spinnaker libgentl libavcodec58...\|grep"^[^ ]"|sort-u)forpkgin"${DEPS[@]}";doaptdownload"$pkg"# 只下载不安装done

apt download在联网机器上把几十个 .deb 全拉下来,目标机完全不需要网络。

4. 相机 SDK 双保险

优先拷官方 deb 包(目标机dpkg -i正规安装,依赖关系自动处理);同时把/opt/spinnaker目录、udev 规则(40-flir-spinnaker.rules)、/etc/ld.so.conf.d/的库路径配置一并打包作为 fallback。udev 规则千万别漏——没有它,USB 相机权限不对,普通用户根本打不开设备。

安装脚本:只增不删,装缺不装全

install.sh的核心纪律:

install_system_deps(){localmissing=()fordebinsystem_packages/*.deb;dopkg=$(dpkg-deb-f"$deb"Package)# 只收集系统里没装的包dpkg-s"$pkg">/dev/null2>&1||missing+=("$deb")done[${#missing[@]}-eq0]&&{echo"系统依赖已满足,跳过";return0;}sudodpkg-i"${missing[@]}"}

三条原则:

  • 只安装缺失的包,已存在的一个不碰;
  • 绝不卸载任何东西——离线环境没有 apt 帮你兜依赖地狱,dpkg -i失败就报错让人工处理,不要自作聪明加--force;
  • 目标已有/opt/spinnaker时先备份成.bak再装,可回退。

最后顺手完成:udev 规则 reload、把用户加入flirimaging组(相机权限)、ldconfig刷新库缓存。

部署后自检:一份 check_env.sh 挡掉 80% 的扯皮

装完先跑自检脚本再启动软件,把环境问题暴露在交付现场之前:

echo"== CPU 指令集 =="grep-o-E'sse4_2|avx|avx2'/proc/cpuinfo|sort-u# 没有 sse4_2 → OpenVINO 直接跑不了;没有 avx2 → 能跑但慢(N3350 就是这种情况)echo"== 内存 =="free-h# < 3.5G 建议加 swap,推理峰值会顶满echo"== 相机设备 =="ls-l/dev/video*echo"== 网卡 =="ipaddr# GigE 相机网口是否配了同网段 IP

这份脚本还有一个隐藏用途:远程排障。现场工人不懂 Linux,让他跑一下脚本把输出发给你,比电话里问"你电脑什么配置"高效十倍。

开机自启

工控机的软件必须断电重启后自己起来。autostart.sh里做三件事:等桌面环境就绪 → 激活 venv → 启动 main.py。用 systemd service 或桌面自启条目均可,注意 DISPLAY 环境变量要等 X 起来才有。

效果

  • 离线包解压后约 865MB、压缩成 tar 约 101MB(预装 venv + 模型 + SDK + 系统 deb),U 盘拷过去,解压 + install.sh + 自检即完成部署,全程不碰网络;
  • 交付多台同型号工控机,环境零差异——因为环境根本不是在目标机上"装"出来的,是"搬"过去的。

小结

  • 离线部署的核心思路:环境不在目标机上安装,而是在联网机器上整体搬运;
  • venv --copies、递归apt download、SDK deb + 目录双保险,三个动作解决 90% 的离线依赖问题;
  • 安装脚本只增不删、装缺不装全——生产环境的系统不是你的试验田;
  • 自检脚本把"环境对不对"变成一份可发送的报告,部署和售后都靠它。

系列文章:

  • 《PyQt 工业检测软件多线程实战:触发、取帧、推理、UI 四条线怎么不打架》
  • 《Python 对接 PLC 实现拍照触发与结果回传——Modbus-TCP 一问一答协议实战》
  • 《YOLOv8 部署到无 GPU 工控机实战:ONNX 导出 + OpenVINO 推理 + 手写后处理》

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询