拓冰建站拓冰建站
首页 / 资讯中心 / 正文

Linux源码编译httpd报错APR not found:原因、三种解法与排查思路

在 Linux 下从源码编译 Apache httpd执行./configure时被一句configure: error: APR not found. Please read the documentation.卡住是很多人的共同经历。我第一次遇到时也有点懵APR 是什么为什么 configure 直接就停住了后来翻文档、看config.log才发现这其实是一个特别典型的“缺少依赖开发包”问题处理起来并不复杂。这篇文章会把 APR 的来龙去脉、报错原理、三种常用解法以及我踩过的坑完整讲一遍适合正在源码编译 httpd、被 configure 检查阶段卡住、或者想以后少在这类问题上浪费时间的朋友。1. 先拆解报错APR 是什么configure 在找什么1.1 报错信息不是乱码它在说“缺依赖”configure: error: APR not found. Please read the documentation.这行输出核心信息就是“APR 没找到”。这里说的“找到”不是指 configure 想下载一个 APR而是它要在你的系统里找到 APR 的头文件、库文件和配置脚本用来完成后续的编译和链接。httpd 的 configure 脚本在检查 APR 时默认会去几个固定位置寻找apr-1-config这个脚本文件常见路径包括/usr/bin、/usr/local/bin、/usr/local/apr/bin等。如果你通过系统包管理器安装过 APR 开发包这个脚本会出现在标准目录里如果你是自己源码编译安装的那一般会出现在你指定的--prefix目录下的bin子目录。configure 找不到它不知道 APR 的版本号、编译参数、头文件位置自然不敢继续往下走于是直接终止并留下这行提示。这里要强调一点不少同学看到“Please read the documentation”会以为是自己操作姿势不对其实这行字是在引导你去看 httpd 源码包里的README、INSTALL文件。打开INSTALL就能看到一句话httpd 需要 APR 和 APR-Util。所以它并不是让你去网上搜什么隐藏技巧而是明确告诉你“编译前的依赖准备没做完”。1.2 APR 和 APR-Util 在 httpd 中干了什么APR 全称 Apache Portable Runtime是 Apache 软件基金会维护的一套跨平台运行时库。它把文件操作、socket、内存池、线程、信号量这些底层能力封装成统一接口让 httpd 可以在 Linux、Unix、Windows 等不同系统上编译运行。你可以把它理解成 httpd 的“地基”之一没有这套库httpd 的很多核心模块根本没法工作。APR-Util 则是在 APR 之上做的更高层封装负责 XML 解析、数据库连接、URI 解析这些相对上层的功能。httpd 编译时这两个库一般需要同时存在所以你在装开发包时最好把apr-devel和apr-util-devel一起装上或者源码编译时把 APR 和 APR-Util 一起编译安装。还有个容易混淆的点APR 是独立于 httpd 的项目。你下载的 httpd 源码包里并不默认包含 APR 源码除非你主动选用--with-included-apr方式。所以每次在干净环境编译 httpd都需要先解决 APR 的依赖问题这不是 bug而是设计如此。2. 修复前花三分钟把当前环境摸清楚2.1 找出系统里已有的 APR 痕迹在动手安装之前我强烈建议先做一轮快速排查搞清楚当前环境到底缺什么。很多情况下你并不是完全没有 APR而是只装了运行时包没装开发包。Red Hat 系的系统可以用rpm -qa | grep -i aprDebian/Ubuntu 系用dpkg -l | grep -i apr如果看到的是apr、libapr1这类包名说明系统里只有运行时库没有-devel或-dev后缀的开发包。编译需要的是后者因为 configure 要靠头文件apr.h和脚本apr-1-config获取编译信息。如果查询结果为空可以再找一下apr-1-config脚本到底在不在find / -name apr-1-config 2/dev/null这个命令会花点时间但能一次性确认脚本是否存在、具体在哪个目录。找到之后可以顺手看下版本apr-1-config --version对 httpd 2.4.x 来说APR 版本一般不要低于 1.5.0建议使用 1.6.x 或 1.7.x。如果系统仓库自带版本太老再考虑源码编译。2.2 确认 httpd 依赖与版本要求除了 APRhttpd 源码编译还会依赖其他东西比如 PCRE、OpenSSL、libxml2、expat。APR 检查只是第一步后面还会检查一堆库。为了不反复重跑 configure我一般会在最开始就把常见编译依赖一次装齐而不是等报错再一个一个补。Red Hat 系基础依赖示例sudo yum install -y gcc make pcre-devel openssl-develDebian/Ubuntu 系对应的是sudo apt update sudo apt install -y build-essential libpcre3-dev libssl-dev注意不同发行版、不同版本里包名会有差异。这一步的目的是“先把编译工具链补全”避免后面又出现pcre not found、openssl not found之类的二次报错。3. 第一种解法系统包管理器安装 APR 开发包3.1 不同发行版对应的安装命令如果系统软件源里能直接找到 APR 开发包那这是最省事、也最推荐的方式。它会把头文件、库文件、apr-1-config脚本都放到 configure 默认查找的标准路径下装完基本不用额外配置。Red Hat / CentOS / Fedorasudo yum install -y apr-devel apr-util-devel如果系统用的是 dnf把 yum 换成 dnf 即可sudo dnf install -y apr-devel apr-util-develDebian / Ubuntusudo apt update sudo apt install -y libapr1-dev libaprutil1-dev注意 Debian 系的运行时库包名是libapr1开发包会多一个-dev后缀叫libapr1-dev。Red Hat 系则正好相反运行时包叫apr开发包叫apr-devel。这个命名差异是很多人第一次栽跟头的地方。3.2 装完后要做的验证装完不要急着直接回去跑./configure先验证一下关键文件是否就位。比如apr-1-config --version或者ls -l /usr/bin/apr-1-configRed Hat 系还可以用rpm -ql apr-devel | grep apr-1-configDebian 系用dpkg -L libapr1-dev | grep apr-1-config确认能找到脚本、版本号也合理再回到 httpd 源码目录重新执行./configure --prefix/usr/local/httpd正常情况下configure 会打印checking for APR... yes然后继续往下走。到这里问题基本就解决了。3.3 为什么这个方案通常最省心但不适合所有人系统包方案的优点很明显自动处理依赖、文件放在标准位置、后续升级方便。但它有个前提系统仓库里的 APR 版本必须满足 httpd 的要求。如果遇到下面这几种情况系统包方案就不太合适了内网环境无法访问软件源安装包需要离线导入。系统版本太老仓库里的 APR 版本过低。需要给 APR 打私有补丁或者想严格控制每个库的版本。希望把 APR 静态编进 httpd做到到处可以拷贝运行。这些场景就得考虑第二种方案也就是源码编译。4. 第二种解法源码编译 APR 并显式指定路径4.1 什么时候需要走源码路线源码编译最大的好处就是“版本可控、路径可控”。我一般在需要定制 APR 编译选项或者目标机器上已经存在一套 APR 但不想动系统库、想隔离部署时会选这条路线。缺点是后续维护成本高自己编译的库不会跟着系统一起升级。另外路径如果没配置好后面启动 httpd 时还可能遇到找不到共享库的问题这些都是需要提前接受的成本。4.2 编译安装 APR 与 APR-Util 的完整步骤先去 Apache 的存档站点下载对应源码包以 APR 1.7.4 和 APR-Util 1.6.3 为例cd /opt wget https://archive.apache.org/dist/apr/apr-1.7.4.tar.gz wget https://archive.apache.org/dist/apr/apr-util-1.6.3.tar.gz tar zxf apr-1.7.4.tar.gz tar zxf apr-util-1.6.3.tar.gz先编译安装 APRcd apr-1.7.4 ./configure --prefix/usr/local/apr make make install编译完 APR 后再编 APR-Util。注意这一步要用--with-apr指向刚才安装好的 APR 目录否则 APR-Util 的 configure 可能会去系统默认路径找造成版本漂移cd /opt/apr-util-1.6.3 ./configure --prefix/usr/local/apr --with-apr/usr/local/apr make make install我用/usr/local/apr作为统一前缀这样最终会得到/usr/local/apr/bin/apr-1-config/usr/local/apr/bin/apu-1-config/usr/local/apr/include/apr-1//usr/local/apr/lib/后续 httpd 的 configure 全靠这些文件定位。4.3 httpd 的 configure 如何接住这套源码版 APR编译 httpd 时就不再指望 configure 去标准路径猜了直接用--with-apr和--with-apr-util把脚本路径告诉它cd /opt/httpd-2.4.58 ./configure --prefix/usr/local/httpd \ --with-apr/usr/local/apr/bin/apr-1-config \ --with-apr-util/usr/local/apr/bin/apu-1-config这里有两种写法--with-apr后面可以接脚本文件的完整路径也可以接安装目录。我习惯直接给脚本文件的路径最直观也最不容易让 configure 猜错。有一点特别值得注意如果之前有一次失败的./configure运行记录它可能会留下config.cache或一堆临时状态。重跑 configure 之前最好先清理一次make distclean或者直接把源码目录里的config.cache删掉。否则 configure 可能读到老缓存出现“我明明装了包为什么还报 not found”的诡异现象。4.4 别忘了动态库运行时路径源码方式编译安装到自定义前缀后httpd 编译时找到库只是第一步运行时系统还要能找到共享库。如果启动 httpd 时提示类似error while loading shared libraries: libapr-1.so.0: cannot open shared object file那就是动态库路径没有注册。解决办法是把它加到系统动态库配置中echo /usr/local/apr/lib /etc/ld.so.conf.d/apr.conf ldconfig然后运行ldconfig -p | grep apr确认libapr-1.so.0已经能被找到。这一步虽然发生在“编译完成之后”但它是源码方式安装必须提前知道的操作否则你会误以为 APR 没编好实际上只是运行时到不了。5. 第三种解法用 httpd 自带的 srclib 编 included APR5.1 思路与适用场景httpd 源码包的srclib目录本来就是一个“给外部子项目预留”的位置。它支持把你准备好的 APR、APR-Util 源码放进去然后 configure 加--with-included-apr让 httpd 在编译时把这两个库一起编出来并直接链接进去。这相当于把 APR 和 APR-Util 变成 httpd 编译过程中的“内部项目”外部系统里有没有 APR 就不重要了。适合的目标环境是机器的软件源不能随便动、不能装-devel包、但又需要把 httpd 编出来的场景。5.2 具体操作步骤假设你已经下好了apr-1.7.4.tar.gz和apr-util-1.6.3.tar.gz先解压 httpdcd /opt wget https://archive.apache.org/dist/httpd/httpd-2.4.58.tar.gz tar zxf httpd-2.4.58.tar.gz cd httpd-2.4.58然后把 APR 和 APR-Util 准备好放到srclib下目录名必须是apr和apr-utilcd /opt/httpd-2.4.58/srclib tar xzf /opt/apr-1.7.4.tar.gz mv apr-1.7.4 apr tar xzf /opt/apr-util-1.6.3.tar.gz mv apr-util-1.6.3 apr-util如果srclib里已经存在同名目录或文件先清理掉不然会残留旧内容。接着回到 httpd 源码根目录cd /opt/httpd-2.4.58 ./configure --prefix/usr/local/httpd --with-included-aprconfigure 会在这个内部源码树中编译 APR 和 APR-Util。整个过程耗时会更长因为相当于多编了两个库。5.3 included APR 的局限和代价这个方案看着省事但有几个点要注意。首先必须把 APR-Util 也放进去。如果只放了apr不放apr-utilconfigure 不会立刻报 APR not found而是在后面检查 APR-Util 时出错到时候反而更难判断。其次后期给 APR 打补丁会比较麻烦。你得改srclib/apr下的源码然后重新编译整个 httpd。如果你更希望 APR 由单独项目维护升级那就别用 included 方式老老实实用系统包或独立源码安装。第三--with-included-apr会改变 httpd 与 APR 的链接方式二进制部署时对运行环境的依赖会少一些但编译产物的体积会更大。对于大多数常规场景这个方案不是首选我更愿意把它当成系统包方案的备用方案。6. 实战复盘从报错到 httpd 启动的完整现场6.1 一台干净机器上发生的事为了方便说明我模拟一台刚装好操作系统的 CentOS 7 机器只有基础工具链没有装过 APR。先装编译基础依赖sudo yum install -y gcc make pcre-devel openssl-devel下载并解压 httpd 源码cd /opt wget https://archive.apache.org/dist/httpd/httpd-2.4.58.tar.gz tar zxf httpd-2.4.58.tar.gz cd httpd-2.4.58执行 configure./configure --prefix/usr/local/httpd终端输出会停在类似位置checking for APR... no configure: error: APR not found. Please read the documentation.此时先别慌。按之前的排查思路来rpm -qa | grep -i apr可能什么都没有也可能只有运行时包。再找一下脚本find / -name apr-1-config 2/dev/null如果没有任何输出说明确实没装开发包。直接安装sudo yum install -y apr-devel apr-util-devel装完验证apr-1-config --version能正常打印版本号后重新执行./configure --prefix/usr/local/httpd这时输出会变成checking for APR... yes checking for APR-Util... yes看到这两个yes说明依赖已经打通。继续make -j2 make install最后启动并验证/usr/local/httpd/bin/apachectl start curl -I http://127.0.0.1/如果能返回 HTTP 响应头说明 httpd 已经跑起来了。6.2 过程中容易出现的连环报错这个流程里最常见的两个“次生报错”一个是装完apr-devel但没装apr-util-develconfigure 会继续报APR-UTIL not found。解决办法很简单把apr-util-devel也装上重新 configure 即可。另一个出现在源码安装 APR 的场景编译正常、configure 也过了但启动 httpd 时报libapr-1.so.0找不到。这不是 APR 的问题是动态库路径没注册。按上一节的方法执行ldconfig或者在启动脚本里设置LD_LIBRARY_PATH。这里的关键是思维要清楚编译时能过说明 configure 阶段已经找到了头文件和脚本运行时找不到说明动态链接器还没发现共享库这是两个阶段的问题不能混为一谈。7. 故障排查速查以后遇到 configure not found 怎么快速定位7.1 不认识报错时先去看 config.log每次 configure 失败时源码目录下都会生成一个config.log里面记录了所有检测项的详细过程。与其在终端最后几行输出里猜原因不如直接打开config.log搜索关键字。比如这次是 APR可以执行grep -n APR config.log或者直接看报错点附近的上下文tail -n 200 config.logconfig.log里通常有“failed program was”之类的段落后面跟着编译器原始输出能帮你定位到真正的失败原因。很多看起来玄乎的 not found其实只是头文件路径、库文件路径没对上。7.2 APR 报错排查对照表我整理了一个常用排查表按现象直接对号入座现象可能原因处理方式configure 报 APR not found完全没有安装 APR 开发包安装apr-devel/libapr1-dev运行时包已装但仍报 not found缺的是开发包不是运行时补装-devel或-dev后缀包已装开发包但仍报 not found脚本不在 PATH或存在多版本混乱用find定位脚本显式指定--with-apr重跑 configure 后仍报相同错误残留了 config.cache执行make distclean或删除缓存文件编译通过但启动时报 libapr 找不到运行时动态库路径未配置写入 ld.so.conf.d 并执行 ldconfig报 APR-Util not found只装了 APR没装 APR-Util安装apr-util-devel/libaprutil1-dev这张表不只能用于 APR很多依赖库的 not found 排查思路都一样先判断是运行时还是开发包再看脚本路径最后清理缓存。7.3 离线环境怎么补依赖内网环境装不了软件源时有一种比较实用的做法在一台能联网的同版本机器上用包管理器把依赖包下载下来再拷贝到目标机器安装。Red Hat 系可以使用yumdownloader --resolve apr-devel apr-util-devel或者dnf download --resolve apr-devel apr-util-develDebian 系可以用apt download libapr1-dev libaprutil1-dev然后把下载到的 rpm 或 deb 包拷贝到目标机器分别用rpm -Uvh *.rpm和dpkg -i *.deb安装。如果包管理器的离线方式也走不通那就回到源码方案把 APR 和 APR-Util 的源码包一起拷贝进去在目标机器上自行编译安装。这个方案不依赖网络只要目标机器有 gcc、make 就能完成。离线环境里我非常建议把源码包提前存好配合--with-apr这种显式指定方式能少踩不少路径上的坑。最后说一个我自己的习惯处理这类 configure 报错时我不太喜欢只记“装某个包”这种零散经验而是会记住一条通用顺序——先确认报错里的库是什么再看系统里有没有对应的开发包最后用显式路径或缓存清理解决“装上了但找不到”的问题。APR not found 只是这条流程里比较典型的一个案例。掌握这个思路之后以后遇到 pcre、openssl、libxml2 相关的 not found你也能很快找到方向。
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门