尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Win10 Cygwin 编译 ipmitool 1.8.19 连 BMC

Win10 Cygwin 编译 ipmitool 1.8.19 连 BMC 手边只有一台 Windows 10 的机器却要连服务器的 BMC 做带外管理这种场景下 ipmitool 基本是绕不过去的。麻烦在于 ipmitool 1.8.19 是个相当纯粹的 POSIX 程序官方只发源码 tarball没有任何 Windows 侧的安装包或者工程文件。所以「win10 下 ipmitool 1.8.19 编译」这件事的本质是在 Windows 上先造一个足够像 Linux 的编译环境再把这份代码原样喂进去。我前后编过四五次第一次用 MSYS2 折腾了大半天最后拿到一个能跑但连不上机器的 exe后来固定用 Cygwin 一套流程走通才发现踩的坑集中在两件事上——OpenSSL 探测失败导致 lanplus 接口被静默砍掉以及编出来的 exe 脱离 Cygwin 目录就跑不起来。这篇就把这两件事的来龙去脉连同完整的命令、开关含义、报错对照一起说清楚。1. 先把结论摆出来为什么 Win10 上编 ipmitool 1.8.19 得绕个弯1.1 ipmitool 1.8.19 依赖了哪些 POSIX 能力很多人第一次打开 ipmitool 的源码目录是懵的一堆.c文件configure脚本Makefile.in看不到任何.vcxproj、.sln。这不奇怪ipmitool 1.8.19 的构建体系是 autotools运行期则依赖了一整套 Unix 世界的约定。我把这份代码实际用到的 POSIX 能力大致归了三类第一类是头文件和基础接口。unistd.h、sys/socket.h、netinet/in.h、arpa/inet.h、sys/time.h、getopt.h、pwd.h、syslog.h、termios.h这些在标准 Windows SDK 里要么没有要么名字对不上。举个最典型的例子网络部分用的是 BSD socket 那一套——socket()、connect()、sendto()、recvfrom()、select()函数名跟 Winsock2 看着一样但 Windows 侧必须先WSAStartup出错要去查WSAGetLastError()而不是errno。ipmitool 全篇按errno写的直接拿 MSVC 编会满地报错。第二类是进程和终端相关。ipmievd这个守护进程部分用到了fork()、setsid()交互式的ipmi_sol、ipmi_tsol依赖readline密码输入走的是getpass()。这些在 Windows 原生环境里没有等价物。第三类是密码学库。lanplus 接口走的是 IPMI 2.0 的 RMCP 协议会话加密用 AES-CBC-128完整性校验用 HMAC-SHA1所以它必须链上 OpenSSL 的libcrypto和libssl。这一点是整个编译过程中最关键也最容易翻车的地方——后面会单独讲。顺带说一个很多人会混淆的点ipmitool 能看的是传感器、SEL 事件日志、FRU、机箱电源状态、SOL 串口重定向这些它看不到 RAID 阵列的详细信息。热词里有人搜「ipmitool 查看 raid」这属于方向错了RAID 得用对应厂商的管理工具比如各家阵列卡的命令行工具ipmitool 顶多能在 SEL 里看到 RAID 控制器上报的一条事件记录。1.2 Cygwin、MSYS2MinGW-w64、MSVC 三条路的取舍对照Windows 上想编这份代码能走的路就三条各自代价差别很大先看表再决定比盲目开工省时间。方案最终产物需要改动源码吗运行期依赖我的评价Cygwinipmitool.exe完全不用改同目录或 PATH 里要有cygwin1.dll及若干加密库 dll最省事一次成功率高推荐MSYS2 MinGW-w64原生 PE 格式 exe需要处理头文件与函数缺口只需要 OpenSSL 的 dll不需要 Cygwin 层产物干净但 serial、SOL 基本残废MSVC / VS2010 等无现成工程得自己写要手工替换大量 POSIX 调用视链接方式而定性价比极低不建议尝试Cygwin 的本质是提供一层cygwin1.dll运行时把绝大部分 POSIX 接口在 Windows 内核上模拟出来。unistd.h、termios.h、fork()、select()这些它全有所以 ipmitool 的源码可以一行不改直接编。代价是产出的 exe 不是原生程序换台机器跑得带上 dll。MSYS2 配 MinGW-w64 走的是另一条路它只提供构建工具链和一部分头文件目标产物是原生 PE。这条路编 lanplus 能成功但termios.h缺失会导致串口接口直接编不过getopt_long也不是所有版本的 mingw-w64 都有实现readline的移植更是麻烦最后你很可能得到一个「能连 BMC 但没法用 SOL 交互」的残缺版本。至于 MSVCipmitool 1.8.19 根本没有官方的 VS 工程文件。有人会照着热词里那些「vs2010 编译报 error MSB6006 cmd.exe 已退出代码为 3」的帖子去试那类报错本身就是自己手搓工程文件时自定义生成步骤里的命令行写错了导致的——在 ipmitool 这个项目上这条路等于从头写一个构建系统不值得。所以下面的流程我全部按 Cygwin 走。2. Cygwin 环境包要一次装齐别中途补2.1 必装包清单与它们各自管什么Cygwin 的安装器是setup-x86_64.exe从官网下最新的就行。装的时候会走到包选择界面默认是Default视图很多开发包不会自动勾上必须手动切到Full视图逐个找或者直接在搜索框里输包名。中途漏装再回来补是完全可以的但如果装到一半才发现少了openssl-devel前面的configure结果就得全部作废重来所以一次装齐更省心。包名作用漏装的后果gcc-coreC 编译器configure 直接报 C compiler cannot create executablesmake构建工具没有 Makefile 的执行能力binutils链接器、ar 等链接阶段报找不到ldopenssl-develOpenSSL 头文件与静态库lanplus 接口被静默关闭libreadline-develreadline 头文件SOL 的交互模式用不了但不影响主功能ncurses/libncurses-devel终端能力库readline 的依赖通常会被自动带上pkg-config依赖探测辅助部分探测脚本找不到库路径wget或curl下载源码只能从 Windows 侧下好再拷进来tar、bzip2解包打不开.tar.bz2libtool、automake、autoconf、git只在用 git 源码时才需要官方 tarball 路线可以不装一个很实用的技巧是Cygwin 的安装器支持命令行静默安装把包清单写进命令里换机器或者重装环境时直接复制粘贴不用再对着界面一个个点。# 假设 setup-x86_64.exe 已经下到当前目录 ./setup-x86_64.exe -q -P gcc-core,make,binutils,openssl-devel,libreadline-devel,ncurses,pkg-config,wget,tar,bzip2还有一点容易被忽略安装类型选All Users还是Just me。如果是公司电脑、没有管理员权限选Just me装到用户目录下后面所有路径都不用考虑权限问题。2.2 源码获取与目录放置的几个细节源码从 ipmitool 的项目主页下载文件名是ipmitool-1.8.19.tar.bz2。页面上一般会给出校验值下完顺手对一下再解压这一步不麻烦但值得做——尤其是在别人机器上操作的时候。有一个坑我必须提醒不要把源码放在带空格或中文的路径下也不要放在Program Files里。autotools 生成的Makefile里对路径的引用在某些环节没有做引号保护路径里有空格configure或者make中途会报出莫名其妙的错误排查起来非常耗时间。我习惯在 Cygwin 的家目录下建一个构建区mkdir -p ~/build cd ~/build # 把 tar 包拷进来后 tar -xjf ipmitool-1.8.19.tar.bz2 cd ipmitool-1.8.19 ls -1正常应该能看到configure、Makefile.in、lib/、src/、include/、contrib/这些。如果configure不在列表里说明你拿的是 git 仓库而不是官方 tarball处理方式不一样下一节讲。另外提一句安全上的事网上能搜到一些「已经编译好的 ipmitool.exe」压缩包来源不明。这类二进制工具要往生产环境里放之前至少要考虑它的可信度问题我自己是不用的宁可花半个小时自己编一遍。3. configure 的开关决定成败lanplus 必须活下来3.1 官方 tarball 与 git 源码在第一步的差异官方发布的ipmitool-1.8.19.tar.bz2里configure脚本是已经生成好的所以解压完直接./configure就行。这一点很重要因为从 git 仓库拉下来的源码只有configure.ac和Makefile.am没有configure你得先用 autotools 生成一遍。如果手上只有 git 源码第一步是这样# 在源码根目录执行 libtoolize --force --copy aclocal autoheader automake --add-missing --copy autoconf或者在有些版本里项目自带一个bootstrap脚本可以直接跑。但这条路上最典型的报错是aclocal-1.16: not found这类原因是你机器上的 automake 版本后缀跟configure.ac里写的AM_INIT_AUTOMAKE版本对不上或者aclocal.m4是别人生成好带过来的。遇到这种情况最省事的做法是绕开各个分步命令直接用autoreconf -i -f它会按当前机器上实际安装的版本重新生成一整套构建脚本版本不匹配的问题基本都能解决。3.2 逐个开关解释与我固定用的那套参数./configure --help能把所有开关列出来但选项名字起得比较随意光看名字不一定知道该不该开。我把几个关键的按「Windows 下要不要开」梳理一遍--enable-intf-lanIPMI 1.5 的会话走 UDP 623 端口协议本身不加密不依赖 OpenSSL。建议开遇到只支持 1.5 的老机器时是唯一退路。--enable-intf-lanplusRMCP也就是 IPMI 2.0会话有 AES 加密和完整性校验必须依赖 OpenSSL。这是现在绝大多数 BMC 的主用接口必开。--enable-intf-open走本机的/dev/ipmi0设备Windows 上没这个设备开着也不会在编译期报错但运行时用不了。开着无妨。--disable-intf-serial串口接口。Cygwin 下termios.h是有的理论能编过但 Windows 上串口设备名是COM1这样的形式跟代码里假设的/dev/ttyS0对不上实际用不了建议关省得留下一个看着能用其实是废的接口。--disable-intf-usbUSB 接口需要 libusbWindows 下没有对应的实现路径关掉。--enable-ipmievd事件守护进程会把 SEL 事件转发到 syslog。做实验或者需要长期监听时可以开日常命令行使用无所谓。我固定用的这套参数./configure \ --prefix/usr/local \ --enable-intf-lan \ --enable-intf-lanplus \ --enable-intf-open \ --disable-intf-serial \ --disable-intf-usb \ --enable-ipmievd如果连不上机器、又怀疑是 OpenSSL 探测的问题可以手动把链接参数塞进去再试一次LIBS-lssl -lcrypto CPPFLAGS-I/usr/include LDFLAGS-L/usr/lib ./configure \ --enable-intf-lan --enable-intf-lanplus --disable-intf-serial --disable-intf-usb注意改过configure参数之后一定要先make distclean再重新configure直接重跑configure有可能复用上一轮的缓存导致开关看起来改了实际没生效。3.3 怎么确认 lanplus 真的编进去了这是整个流程里最容易吃亏的一步。OpenSSL 探测失败时configure不会报错退出它只会打印一行提示然后把 lanplus 接口静默关掉。你后面make顺顺利利编完拿到 exe一执行ipmitool -I lanplus ...才发现接口根本不存在白跑一趟。所以configure跑完之后必须去它的输出末尾看一眼有没有类似这样的一行** OpenSSL libraries not found - lanplus interface disabled **有这行就说明白干了得回去查openssl-devel是不是真装上了。确认方式有两种# 直接看头文件在不在 ls /usr/include/openssl/ssl.h # 看 config.log 里 OpenSSL 探测那一段的结论 grep -in openssl config.log | head -20还有一种更直接的验证手段看生成的离底层产物里有没有把加密库链进去grep -n ^LIBS Makefile | head -5输出里应该能看到-lssl -lcrypto或者 Cygwin 下对应的-lssl -lcrypto -lz这种组合。如果LIBS是空的那就是真的没链上。另外补一句版本上的经验OpenSSL 3.x 系列对一部分老接口打了废弃标记编 ipmitool 1.8.19 时可能刷出大量 deprecated 警告一般不影响出产物。但如果你的环境把警告当错误处理或者编译参数里带了-Werror就会直接中断。这种情况加一个CFLAGS-Wno-deprecated-declarations重新configure通常就能过真遇到因 API 变更导致的硬编译错误最省事的路子是退到 1.1.1 分支的 OpenSSL而不是去改源码打补丁。4. make 之后的事产物、依赖和最简连通性验证4.1 编译过程中的中断点与 distclean 时机configure过了之后编译本身通常很顺make -j4-j后面跟的数字按自己机器的核数来Cygwin 下nproc命令也能用写成make -j$(nproc)也行。整个编译顺序大致是lib/里的公共代码、src/plugins/下的各个接口实现、最后是src/里的主程序。实际编译中最容易卡住的地方有几个一是src/ipmi_sol.c之类的文件如果环境里没有 readline相关代码块会被条件编译跳掉一般不报错二是ipmievd那部分涉及守护进程的代码三是从旧版本升上来时残留的.o文件导致的链接冲突。这里有个习惯值得养成只要动过configure的开关、或者换过工具链版本第一件事永远是make distclean。它会把Makefile、config.h、所有中间产物清干净比手删靠谱。清完之后重新configure、make两遍的日志才好对比。编译完成后产物在源码树里长得是这样ls -l src/ipmitool.exe src/ipmievd.exeipmitool.exe是我们真正要的东西。先验证一下版本./src/ipmitool.exe -V正常输出一行ipmitool version 1.8.19。到这一步说明编是编出来了但离能用还差一步——依赖库。4.2 把 exe 搬出 Cygwin 的两种做法刚编出来的ipmitool.exe只有在 Cygwin 的 shell 环境里才能跑因为它依赖cygwin1.dll以及若干加密、readline 相关的 dll。这时候你可以用cygcheck把所有依赖列出来cygcheck ./src/ipmitool.exe输出里会有一段 dll 列表除了系统 dll还会看到cygwin1.dll、cygcrypto-*.dll、cygssl-*.dll、cygreadline*.dll、cygncursesw-*.dll这类。这些都在 Cygwin 安装目录的bin下。做法一照单全拷。新建一个目录把ipmitool.exe和cygcheck列出来的那几个 Cygwin 相关 dll 一起丢进去直接在这个目录里执行。这种做法适合临时拷到别的 Windows 机器上救急。mkdir -p /cygdrive/d/ipmi-tool cp src/ipmitool.exe /cygdrive/d/ipmi-tool/ cp /bin/cygwin1.dll /bin/cygcrypto-1.1.dll /bin/cygssl-1.1.dll /cygdrive/d/ipmi-tool/做法二在目标机上装一个最小 Cygwin。只勾openssl-devel相关的运行库然后把 exe 丢进bin目录。这样省得一个个 dll 对版本。注意cygwin1.dll是运行时核心版本必须跟编译时的环境匹配。如果目标机器的PATH里已经存在另一个版本更老的cygwin1.dll比如你装过别的 Cygwin 系工具加载的时候会优先命中旧的那个可能出现一些完全没有道理的运行时报错。判断方法就是进到 exe 所在目录用./ipmitool.exe -V显式执行看是不是正常输出。4.3 第一条真实命令与它的预期输出假设要连的 BMC 地址是10.0.0.20账号ADMIN。第一个建议是不要用-P在命令行里写明文密码那条命令会原封不动进 shell 历史ipmitool 支持从环境变量读密码export IPMI_PASSWORD你的密码 ipmitool -I lanplus -H 10.0.0.20 -U ADMIN -E chassis status-E就是「从IPMI_PASSWORD环境变量取密码」。第一条命令建议用chassis status因为它返回的信息少、交互简单成功与否一眼能看出来。正常输出大致是这样System Power : on Power Overload : false Power Interlock : inactive Main Power Fault : false Power Control Fault : false Power Restore Policy : always-off Last Power Event : Chassis Intrusion : inactive Front-Panel Lockout : inactive Drive Fault : false Cooling/Fault : false看到这堆状态值说明 lanplus 会话完整建立起来了。接着可以按需往下探ipmitool -I lanplus -H 10.0.0.20 -U ADMIN -E mc info # BMC 固件版本、厂商 ipmitool -I lanplus -H 10.0.0.20 -U ADMIN -E fru print # 机箱、主板、电源的 FRU 信息 ipmitool -I lanplus -H 10.0.0.20 -U ADMIN -E sdr elist # 传感器列表 ipmitool -I lanplus -H 10.0.0.20 -U ADMIN -E sel list # 系统事件日志 ipmitool -I lanplus -H 10.0.0.20 -U ADMIN -E sol activate # 串口重定向交互式如果-I lanplus直接报密码错或者会话建立失败别急着怀疑密码先换成-I lan试一条ipmitool -I lan -H 10.0.0.20 -U ADMIN -E chassis statuslan走的是 IPMI 1.5 明文会话不需要 OpenSSL。如果lan能通而lanplus不通那问题多半在加密套件协商上——现在不少 BMC 对 cipher suite 3 之外的选择更友好可以试试指定套件号ipmitool -I lanplus -C 17 -H 10.0.0.20 -U ADMIN -E chassis status如果两个都不通那就是账号权限、网络可达性或者 BMC 侧的访问控制配置问题跟编译没关系了。SOL 会话里默认的转义符是~进去之后按~?能看帮助~.是断开并退出会话。这个组合在 Cygwin 的终端里表现正常用 cmd 窗口就未必后面会讲到。5. 报错对照编译期和运行期分别踩过什么5.1 编译期报错归类编译期的报错其实就那几类按发生阶段区分比按字面意思猜要快得多。下面这张表是我自己遇到过并且能稳定复现的阶段现象根因处理configure** OpenSSL libraries not found - lanplus interface disabled **openssl-devel没装或头文件路径不对补装后make distclean重来configureC compiler cannot create executablesgcc 未装全或路径含空格/中文或杀软拦截了临时文件看config.log末尾换纯英文短路径configurecannot find install-sh, install.sh, or shtool解压不完整或目录结构与预期不符重新解压确认在源码根目录执行bootstrapaclocal-1.16: not foundautomake 版本后缀与configure.ac声明不符改用autoreconf -i -fmakeNo rule to make target Makefileconfigure 没成功或不在源码根目录先确认Makefile存在makereadline/readline.h: No such file or directory缺libreadline-devel补装或用--disable相关选项放弃 SOLmakeundefined reference to SSL_CTX_new链接阶段少了-lssl检查configure探测结果必要时手动传LIBSmakeMinGW 路线上fatal error: termios.hmingw-w64 不带 termios关掉 serial 接口makeMinGW 路线上undefined reference to getopt_long缺 getopt 实现补一个 getopt 实现或换 Cygwin 路线这里展开说两个。第一个是 OpenSSL 那行提示。它的迷惑性在于输出是一行以**包裹的普通提示不是errorconfigure的退出码是 0echo $?会告诉你成功。新手看到这个很容易直接往下make。我建议养成一个习惯configure结束后不看最后几行的一律grep -i disabled\|not found config.log扫一遍凡是带这两个词的都要确认是不是预期内。第二个是路径含空格的问题。它在不同阶段的表现完全不一样有时是configure报编译器和临时文件的问题有时是make里某个命令找不到文件。共同点是报错信息跟「路径」八竿子打不着。所以与其事后排查不如一开始就把源码放在~/build这种干净路径下。5.2 运行期才暴露的问题编过make不等于能用运行期的问题往往更绕。找不到 dll。现象是双击 exe 弹窗提示缺cygwin1.dll或者命令行里报error while loading shared libraries。原因是 dll 不在同目录也不在PATH里。按 4.2 节的办法拷齐就行。接口名无效。执行ipmitool -I lanplus ...报接口不存在八成是编的时候 lanplus 被砍掉了。回头看 3.3 节重新configure并确认提示。能建会话但读不出数据。权限问题居多。IPMI 的账号分几个权限等级只读账号能执行chassis status、sdr elist但执行电源控制之类的操作会被拒。这种报错信息通常比较直白看一眼就知道是权限而不是编译。SOL 里终端行为错乱。退格键不删除字符、回车不换行、方向键出来一堆^[[A。这类问题跟编译没关系是终端类型的问题。解决办法是在 Cygwin 的 mintty 里跑而不是在 Windows 的 cmd 窗口里跑同时确认TERM环境变量是xtermexport TERMxterm输出里的中文乱码。有些 BMC 的 FRU 或者传感器名称是中文在 cmd 窗口里显示成乱码。可以把代码页切到 UTF-8# 在 cmd 里执行 chcp 65001顺带说一个跟编译无关但很实用的提醒这类带外管理接口不要暴露在公网可达的位置账号密码也别图省事用弱口令。带外管理口一旦被摸进来等于直接拿到了机器电源和串口的控制权。6. 后续维护把一次编译变成可复现的流程6.1 固化安装包清单与构建脚本第一次编译成功之后如果不做任何记录半年后换台机器再来一次八成还得重新踩一遍。我的做法是留两个文件。一个是cygwin-packages.txt内容就是setup-x86_64.exe -q -P ...后面那一串包名用逗号分隔随时能复制粘贴重建环境。另一个是源码根目录下的build.sh把完整参数写死#!/bin/bash set -e make distclean || true ./configure \ --prefix/usr/local \ --enable-intf-lan \ --enable-intf-lanplus \ --enable-intf-open \ --disable-intf-serial \ --disable-intf-usb \ --enable-ipmievd make -j4 ./src/ipmitool.exe -Vset -e是关键任何一步失败就停不会一路错到底还假装成功。最后那行-V是收尾自检版本号打出来才算这次构建真结束。同时建议把编译产物整理成一个独立目录exe 加依赖的 dll 放一起再附一个最简单的调用示例这样交给同事的时候不用再解释半天。6.2 升级版本时要复查的地方ipmitool 1.8.19 是 1.8.x 这条线的收尾版本之一它跟 1.8.18 之间主要是 bug 修复和一些细节增强configure的开关集合基本没变所以上面这套流程对 1.8.18 也大体通用。但如果以后要跳到更新的版本有几个地方必须重新确认。第一是依赖库的要求是否变了。项目对 OpenSSL 最低版本的要求可能提高如果是老环境可能出现新版本编不过的情况这时候要么升 OpenSSL要么就停在能编过的版本上。第二是开关名有没有增减。./configure --help的输出是最权威的升级前跑一遍跟旧版本对比一下选项列表比看变更日志快。曾经就有版本把某个接口的默认启用状态改过不看开关直接沿用旧参数结果编出来的东西功能不对。第三是目录结构有没有调整。产物路径、头文件位置在版本之间偶尔会挪脚本里写死的路径要跟着改。最后分享一个我自己的判断标准这套自编译流程值不值得维护取决于你手头是不是长期只有 Windows 环境。如果只是偶尔连一次 BMC其实在 Linux 环境下装现成的包会快得多一条包管理命令搞定但如果你长期在一台 Windows 10 工作站上做带外运维把这套 Cygwin 构建链路固化下来配上build.sh和依赖清单一次投入能省掉后面几十次的环境折腾。
返回列表