做EPICS控制系统的朋友,这几年只要一聊到操作员界面,基本绕不开两件事:老前辈BOY越来越扛不住新需求,新来的Phoebus到底行不行。我在实验室里从编译到上线折腾过几轮,可以负责任地说,Phoebus确实值得投入时间,但它的安装、配置和传统CSS/BOY完全不一样,照着旧经验来,大概率会卡在各种奇怪的地方。这篇是“EPICS Phoebus手册”的第一篇,先把最基础的环境准备、编译安装、首次启动和常见坑讲清楚。不管你是给同步辐射、加速器还是各类测试台架做控制系统,只要准备在EPICS生态里换用Phoebus,这篇笔记应该能帮你省掉不少弯路。
1. Phoebus是什么?为什么值得花时间
别急着敲命令,先花几分钟把Phoebus的定位搞清楚。EPICS生态里,操作员界面这块最经典的方案是EDM和CSS/BOY。EDM出现得早,功能基础,界面风格停留在上世纪;CSS/BOY基于Eclipse RCP和SWT,插件体系强大,但启动慢、内存占用高、界面观感偏“工程风”,在触屏和高分辨率屏幕上表现也一般。这几年新项目要么硬着头皮继续用BOY,要么转头去试Phoebus。
Phoebus可以看作是CS-Studio的下一代版本,核心变化是用JavaFX替换了SWT。JavaFX在硬件加速、CSS样式、触控支持、异步渲染这些方面比SWT好太多,所以Phoebus界面明显更现代,滚动、缩放、刷新都更流畅。更关键的是,Phoebus把原来CSS里的一大堆功能拆成了独立模块,报警、数据浏览、日志、扫描、显示编辑器各干各的,你可以只挑需要的模块组合,也可以单独跑某个服务,架构上比“全家桶”清晰很多。
我在实际项目中体会最深的一点是:Phoebus不再像CSS那样要求你启动一个巨大的Eclipse工作台,而是提供了一个非常轻的启动入口。你甚至可以先跑一个最小界面,只是看看PV连接、打开一张显示文件,后面再按需把报警服务、归档引擎这些重型组件加上去。这种“先轻后重”的节奏,特别适合从零开始搭建控制界面的团队,也适合给老项目做渐进式迁移,不用一次推倒重来。
在继续之前,我先把几个后续会反复出现的概念统一一下,免得后面绕晕:
- Phoebus产品(Product):一组打包好的模块集合,可以理解为某个站点定制后的完整控制界面程序。官方发布包和自编译产物都属于产品。
- OPI/显示文件:操作员界面文件。BOY时代是.opi,Phoebus沿用了Display Builder,默认格式还是带.bob后缀的显示文件,但能够打开部分旧.opi。
- PV:EPICS里的过程变量,Phoebus里的所有显示、报警、数据记录都围绕PV展开。
- IOC:输入输出控制器,是PV的数据来源。
- settings.ini:Phoebus的用户偏好配置文件,相当于老CSS里的preferences,很多关键参数都从这里读。
2. 安装前的准备:版本、环境和依赖
2.1 Java版本与操作系统
Phoebus是基于JavaFX的纯Java应用,所以Java环境是头等大事。官方目前要求JDK 17起步,我建议有条件直接上JDK 21 LTS。JDK 8和JDK 11我都试过,老版本在编译阶段就会报错,运行阶段更别指望,所以别在这种地方省事。
操作系统方面,Linux、Windows、macOS都在支持列表里。但生产环境我强烈建议用64位Linux,尤其RHEL/CentOS或Ubuntu LTS。倒不是说Windows跑不了,而是部署、服务托管、字体渲染、日志管理这些后续操作在Linux上顺手得多。我自己踩过比较深的坑是,Windows上如果同时装了多个Java版本,phoebus.sh或bat脚本很可能找不到正确的java路径,最后界面直接闪退,排查起来很费劲。
2.2 从源码构建还是直接使用发布包
这是新手最容易纠结的问题。我的建议很简单:如果只是部署运行、做显示画面、接IOC,直接下载官方发布包,别自己编译。官方Release页面会提供针对各平台的压缩包,里面已经打包好了可运行的jar、启动脚本和依赖的JavaFX运行时,解压就能用。自己从源码编译的主要目的一般是为了二次开发,比如想改显示组件、加自定义插件、调试某个模块,这时候才需要搭建完整构建环境。
有一个“中间态”方案也值得推荐:先用发布包把手头项目跑起来,与此同时在另一台开发机上拉源码做研究和二次开发。这样生产使用和研究学习两条线分开,互不干扰。我早期的教训就是在一台机器上既跑开发构建又跑生产部署,结果Maven仓库里的模块版本一升级,生产环境的启动就跟着出问题,排查了半天才发现是本地缓存搞的鬼。
2.3 Maven、Git与国内镜像配置
如果决定从源码构建,需要准备Git、Maven 3.8以上和一个能访问外网或镜像仓库的网络环境。源码在GitHub上,用git clone拉取即可。构建过程会下载大量依赖,在国内网络环境下Maven Central经常慢得让人怀疑人生,我一般会先配置阿里云镜像,把Maven默认的central仓库替换掉。
Maven的镜像配置在~/.m2/settings.xml,没有这个文件就新建。一个最小可用的配置如下:
<settings> <mirrors> <mirror> <id>aliyun</id> <name>Aliyun Maven Mirror</name> <url>https://maven.aliyun.com/repository/public</url> <mirrorOf>central</mirrorOf> </mirror> </mirrors> </settings>配置完可以执行mvn -v看一下,再随便构建一个小项目验证依赖是否能正常下载。我遇到过不少初学者卡在这里,Maven提示超时或无法解析依赖,最后发现是settings.xml格式错误或镜像URL写错。注意mirrorOf要对应central,不能写*,否则会把其他仓库也强制指向镜像,反而引发问题。
3. 编译安装全过程实录
3.1 拉取源码与选择版本
我在这次实操中用的是Phoebus 4.7.4。版本选择上我的经验是别追最新,也不要选太旧,GitHub Release页面里标了“Latest release”的版本一般经过社区较多验证,适合大部分人。想更稳的话,可以看一下Release Notes里对Java版本的说明,再和自己的运行环境对照。
拉取源码:
git clone https://github.com/ControlSystemStudio/phoebus.git cd phoebus git checkout 4.7.4先用git checkout切到明确的发布版本,比直接在master分支上构建更可复现。master分支是开发主线,随时可能有新改动导致构建失败或运行时异常。我试过在master上构建,经常遇到某个模块刚改了接口,另一个模块还没跟上,编译就挂了。固定版本号是给自己省事。
3.2 执行Maven构建
在phoebus根目录执行:
mvn -DskipTests clean package这里有几个参数要说明。clean会清掉之前的构建产物,避免旧文件干扰;-DskipTests跳过单元测试,构建速度能快不少,但注意这个参数只是不跑测试,测试代码还是会编译的,如果想彻底跳过测试编译需要加-Dmaven.test.skip=true。package会编译当前多模块项目并打包出jar。
如果想利用多核CPU加速,可以加-T 1C表示每个CPU核跑一个模块并行构建。我实测下来并行构建能省不少时间,但偶尔会看到模块间依赖导致的偶发失败,这时去掉并行参数再跑一次通常就通了。
整个构建过程会持续几分钟到十几分钟,取决于网络和机器性能。第一次构建时依赖下载最耗时,后续构建会快很多。看到BUILD SUCCESS就说明编译完成了。
有一点必须提醒:如果你的目的是把中间模块安装到本地Maven仓库供其他项目引用,要用install而不是package。在Phoebus主仓库内做整体构建时,package已经够用,因为Maven reactor会处理模块间依赖;但如果你拆出某个子模块单独构建,或者自己写了基于Phoebus的插件工程,就需要先mvn -DskipTests install把Phoebus相关模块装进本地仓库,否则外部工程找不到依赖。
3.3 找到构建产物并确认启动方式
构建完以后,很多人会愣住:到底启动哪个jar?Phoebus是多模块项目,各模块的jar散布在各自target目录下。对这个系列手册的读者来说,最关心的通常有两个东西。
最小启动入口是core/ui/build/下的jar,比如phoebus-ui-4.7.4.jar。这个jar可以用来快速验证Phoebus框架能否跑起来,但它包含的应用模块有限,报警、数据浏览这些功能不一定齐全。如果你需要完整的操作员界面,应该去产品打包目录找,常见的是phoebus-product或distribution这类子模块的target目录,里面会生成对应平台的压缩包,解压后能看到phoebus.jar、phoebus.sh、phoebus.bat和lib等文件。
不同版本的产品模块名可能略有差异,别死记路径,用下面这条命令搜索:
find . -name "phoebus*.jar" -o -name "product*.zip" | grep -v sources如果你用的是官方发布包,就不用关心这些目录结构了,解压后直接看启动脚本。
3.4 写一个最小可用的settings.ini
Phoebus的运行参数大量集中在settings.ini里。这个文件的核心作用是告诉Phoebus你的PV网络、IOC地址、日志级别等关键信息。没有它,Phoebus也能启动,但很可能找不到你的IOC,因为默认的Channel Access广播行为不一定适应你的网络环境。
我的建议是,第一次启动前就建立一个工作目录,把配置文件单独放好。比如在/opt/phoebus/conf下新建settings.ini,内容先写这几项:
org.phoebus.pv.ca/addr_list=192.168.1.255 org.phoebus.pv.ca/auto_addr_list=true org.phoebus.pv.ca/max_array_bytes=10000000addr_list里填的是IOC所在子网的广播地址,或者具体IOC的IP列表。以我的经验,如果你和IOC在同一个子网内,auto_addr_list=true可以自动探测,但如果IOC不在本地子网,就必须把地址写进去。max_array_bytes是针对波形记录等大数据量的PV,默认值经常不够,项目里如果遇到数组截断、波形显示不全,十有八九是这里没调。
这里有一个通用原则:settings.ini里的配置项格式是“模块名/配置键=值”,跟老CSS的preferences结构类似。你不一定记得住每个键,但Phoebus界面里的Settings面板可以查看和修改,改完会同步到这个文件。
3.5 启动Phoebus并连接本地IOC
我习惯把环境变量也一起固化到启动脚本里,避免每次手敲。下面这个run_phoebus.sh是我在Linux上常用的模板:
#!/bin/bash export JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64 export PATH=$JAVA_HOME/bin:$PATH export EPICS_CA_ADDR_LIST="192.168.1.255" export EPICS_CA_AUTO_ADDR_LIST=no export EPICS_CA_MAX_ARRAY_BYTES=10000000 cd /opt/phoebus ./phoebus.sh -settings /opt/phoebus/conf/settings.ini给脚本加执行权限后运行:
chmod +x run_phoebus.sh ./run_phoebus.sh如果没有IOC可以先造一个简单的,用EPICS base里的softIoc就能实现。假设我写了一个/tmp/demo.db:
record(ai, "DEMO:Temp") { field(VAL, "25.5") }然后启动IOC:
softIoc -d /tmp/demo.db等Phoebus界面起来后,打开菜单里的PV Probe或直接用显示组件绑定DEMO:Temp,如果能读到25.5,说明Phoebus到IOC的链路已经通了。第一次看到PV值刷出来的时候,整个环境搭建就算是走通了。
3.6 Java模块和JavaFX的坑
如果你是直接用官方发布包,自带的启动脚本已经处理好了JavaFX模块路径,基本不会遇到JavaFX问题。但如果你自己用源码构建的jar启动,则很可能报NoClassDefFoundError: javafx/application/Application。
原因很简单:Phoebus使用JavaFX,而JDK自从Java 11起不再自带JavaFX,需要单独引入。自己跑源码jar时,要么确保系统装了openjfx,要么在启动命令里显式指定--module-path指向JavaFX的lib目录。最省心的做法还是用发布包里的脚本,那里面已经把这些参数写好了,没必要自己折腾。
4. 界面与基本操作:第一次上手体验
4.1 主窗口布局
Phoebus启动后的界面比CSS清爽很多,默认是一个多标签的窗口,顶部是菜单栏和应用启动区,左侧或顶部根据布局设置会有导航栏,底部是状态栏。绝大多数操作员界面功能都集中在“应用”菜单里。
第一次打开时先别急着连真实设备,Phoebus支持模拟PV,这对于熟悉界面和调试显示文件非常方便。模拟PV的格式一般是sim://开头,比如sim://sine能产生正弦波,sim://ramp产生斜坡信号。还有局部变量PV用loc://前缀,比如loc://x(5)表示一个初始值为5的本地PV,只在当前Phoebus实例中有效。
我建议新手用模拟PV完成第一次完整流程:新建显示文件,放置一个文本组件,绑定sim://sine,启动运行时模式,看数值是否在变化。整个过程不碰任何硬件,但把Phoebus的核心操作都过了一遍。
4.2 创建第一个显示画面
在菜单里找到“Display”相关项,新建显示文件,Phoebus会打开Display Builder编辑器。左侧是组件面板,中间是画布,右侧是属性视图。从组件面板拖一个“Text Update”或“PV"控件到画布上,在属性里填PV名sim://sine,然后切换到运行时模式。
这里我特别想提醒一个操作习惯:Phoebus的编辑模式和运行模式很容易混淆,很多新人在编辑器里点了半天没反应,才发现自己一直在编辑模式。右下角或工具栏的状态切换要提前适应。另外,保存显示文件时注意格式.bob是Phoebus原生格式,别和旧版.opi搞混。
4.3 从BOY迁移旧显示文件
手里积攒了大量BOY的.opi文件的团队,最关心的就是能不能直接拿到Phoebus里用。官方Display Builder支持导入.opi,启动后可以用“打开显示文件”方式选择.opi文件。但我要泼一盆冷水:兼容性并不是100%,特别是涉及旧CSS专用组件、自定义脚本、某些复杂行为时,经常需要手工调整。
我的迁移建议是分三步走:
- 先批量导入旧文件,在编辑器里打开,逐个看哪些组件报错、哪些行为不对。
- 把不兼容的组件用Phoebus原生组件替换,不要指望自动转换能一步到位。
- 在测试环境下和真实IOC联调,重点检查脚本逻辑、动态属性和颜色规则。
如果你手头有成百上千个OPI,建议先挑一个典型画面做完整迁移,摸索出一套适合自己项目的转换规范,再推广到其他文件。我见过团队花了一周时间迁移完所有文件,最后发现大量细节错误,又花了两周返工,反而比慢慢迁移更慢。
5. 常见问题与排查技巧实录
Phoebus安装和首次启动这个阶段,我积累了不少“踩坑记录”,这里按现象排列,方便大家对照排查。
| 现象 | 常见原因 | 排查方法 |
|---|---|---|
| 启动即闪退,无界面 | Java版本过低或JavaFX模块缺失 | 确认JDK 17+,使用官方发布包启动脚本,或在控制台手动执行java -jar看报错 |
| 构建时报“UnsupportedClassVersionError” | Maven使用的JDK版本和项目要求不一致 | mvn -v查看Maven使用的Java版本,调整JAVA_HOME |
| Maven依赖下载超时 | 网络访问Maven Central慢 | 配置阿里云镜像,重新构建 |
| 能启动但找不到IOC的PV | 广播地址或地址列表配置不对 | 用caget DEMO:Temp验证命令行能否读到,检查EPICS_CA_ADDR_LIST |
| 波形显示截断 | max_array_bytes设置过小 | 调大EPICS_CA_MAX_ARRAY_BYTES并同步settings.ini |
| 中文文字显示成方块 | 系统缺少中文字体或JavaFX字体渲染问题 | 安装noto CJK或文泉驿字体,必要时指定-Dprism.fontdir |
| 界面卡顿、GPU占用异常 | JavaFX渲染受驱动影响 | Linux下尝试启动参数-Dprism.order=sw强制软件渲染 |
| 启动后提示端口被占用 | 报警、日志等模块的默认端口冲突 | 检查是否有旧CSS实例在运行,或修改settings.ini中的端口配置 |
5.1 启动闪退的排查思路
闪退类问题最让人头疼,因为窗口一闪而过,根本看不到报错。我的建议是无论如何都先用命令行方式启动一次,而不是双击启动脚本。在终端里执行./phoebus.sh -settings ...,所有的Java异常和日志都会直接打在控制台里,错误原因一目了然。
最常见的启动闪退是Java版本不对。Phoebus在启动时会做模块检查,老版本JDK直接抛出不兼容异常。其次是内存不足,如果.bob显示文件很大,或同时打开多个大型界面,建议在启动脚本里加-Xmx4g之类的堆大小参数。启动脚本里有个PHOEBUS_JAVA_OPTS环境变量,可以用来追加JVM参数。
5.2 PV连接不上时的排查顺序
先判断是不是Phoebus自己的问题。我积累的排查顺序是:先用命令行工具验证IOC可达性,比如caget或caput,如果命令行能读到PV,说明IOC和网络都没问题,问题大概率出在Phoebus的网络配置上。接着检查EPICS_CA_ADDR_LIST和auto_addr_list,跨网段时必须手动指定地址。最后检查防火墙或安全组策略,Channel Access使用UDP 5064和TCP 5065端口,很多跨网段问题都是端口被防火墙拦截导致的。
还有一个很容易被忽略的点:如果IOC端设置了EPICS_CA_MAX_ARRAY_BYTES,Phoebus端也要对应调大,否则大数据量波形读不全。这个坑我帮别人排查过多次,现象是数据值能读到,但数组长度总是被截断,一开始还误以为是IOC记录的问题。
5.3 中文显示与字体问题
Phoebus在Linux下显示中文经常出问题,典型表现是界面上中文变成一排水口一样的方块。这不一定是代码问题,而是JavaFX找不到合适的中文字体。Debian/Ubuntu上安装fonts-noto-cjk或fonts-wqy-zenhei基本能解决:
sudo apt install fonts-noto-cjkWindows和macOS一般没有这个问题,因为系统自带的中文字体JavaFX基本都能识别。如果还不行,可以在启动脚本里通过-Dprism.fontdir=/usr/share/fonts指定字体目录。
5.4 与旧CSS/BOY同时部署的冲突
有些团队在过渡期需要让Phoebus和老的CSS/BOY并行运行。我遇到过的最典型冲突是端口占用,Phoebus的报警、日志、存档等模块默认端口可能和老CSS冲突。解决办法是错开端口,比如在settings.ini里把报警服务器的端口改成其他值。其次是日志目录冲突,两边默认日志路径如果一样,会产生相互覆盖的假象。建议Phoebus单独指定-log参数或settings.ini里的日志路径,让两边互不干扰。
6. 我自己最后想多说两句
这套环境搭好之后,Phoebus的潜力才算刚刚打开。报警服务、存档引擎、数据浏览、权限系统这些模块,都是后续可以逐个接进来的。手册第二篇我打算写报警系统的配置和服务端部署,那部分坑更多,但收益也最大。
最后分享一个我自己的习惯:凡是涉及Phoebus的启动脚本、settings.ini、显示文件,全部纳入版本管理。看似不起眼,但组件升级、换机器、团队协作时,这套配置就是你最可靠的回退点。我见过不止一个团队因为配置文件随手改、随手丢,最后环境怎么搭起来的都说不清楚。控制系统的本质是可靠和可复现,Phoebus只是工具,但工具用得好不好,往往从第一天配环境时就决定了。