资讯动态

Ubuntu源码编译卡在checking?定位与解决网络阻塞问题

发布时间:2026/10/21 3:44:01 来源:尧图企业网站定制
1. 编译卡在 checking 的本质不是慢是卡住了如果你在 Ubuntu 上从源码编译过软件大概率见过这个场景敲完./configure终端刷出一行checking for gcc...然后光标就停在那里一分钟、五分钟、十分钟纹丝不动。你以为是机器性能不行换了台配置更高的机器结果还是一样。问题根本不在 CPU 算力而在于配置脚本正在等待一个永远不会返回结果的网络请求。这个现象在源码编译圈子里极其常见尤其是编译那些依赖 autotools 构建系统的项目时。configure脚本在正式生成 Makefile 之前会做大量环境探测工作检查编译器是否存在、检查某个头文件能不能用、检查某个库的版本号够不够。这些检查绝大多数是本地操作速度很快。但有一类检查会触发网络访问一旦网络环境不通畅脚本就会一直阻塞在超时等待上表现出来就是一直在 checking。我最早踩这个坑是在一台内网机器上编译一个图像处理库。那台机器没有外网访问权限./configure跑了四十分钟还没结束用strace跟了一下才发现进程卡在一个connect()系统调用上目标地址是某个外部主机。从那以后我就养成了一个习惯编译任何源码之前先看一眼 configure 脚本里有没有网络探测逻辑。这篇文章适合所有在 Ubuntu 上从源码编译软件的人不管你是刚接触 Linux 编译的新手还是已经编译过几十个项目的老手。我会把为什么卡和怎么解决这两件事讲透给出可以直接复制粘贴的操作步骤也会分享一些我这些年积累的排查技巧和避坑经验。2. 编译流程拆解configure 阶段到底在干什么2.1 从源码到可执行文件的三步走在解决问题之前有必要把源码编译的完整流程理清楚。Ubuntu 下从源码安装软件标准流程是三步./configure探测当前系统的环境生成适配本机的 Makefilemake根据 Makefile 里的规则调用编译器把源码编译成目标文件再链接成可执行文件make install把编译好的文件复制到系统指定目录很多人以为编译慢是第二步make的问题但实际上卡在 checking 的现象几乎全部发生在第一步./configure阶段。因为make阶段做的是纯粹的编译和链接工作不涉及网络请求。而configure阶段要做环境探测某些探测逻辑会尝试访问网络。这里有个容易混淆的点用户描述的make 时一直在 checking严格来说不准确。make命令本身不会输出checking字样那些checking for xxx...的输出全部来自configure脚本。所以当你看到终端在刷checking说明你还在 configure 阶段或者你用的是一条把 configure 和 make 串起来的命令比如./configure make实际卡住的是前半段。2.2 configure 脚本的网络探测逻辑configure脚本由 autoconf 工具生成本质上是一个超长的 shell 脚本。它在探测环境时会执行大量的测试用例。大部分测试是本地操作比如检查gcc能不能编译一个最简单的 C 程序检查stdio.h头文件是否存在检查某个函数的签名是否匹配但有一类测试会触发网络访问常见的有这几种第一种是检查依赖库的在线版本。某些项目的 configure 脚本会尝试连接软件包仓库确认依赖库的版本是否满足要求。这种设计在开发者本机可能没问题但在内网环境或者网络受限的环境下就会卡住。第二种是下载辅助脚本或数据文件。一些项目在 configure 阶段需要下载额外的构建工具或配置文件如果下载源不可达脚本就会一直等待超时。第三种是 DNS 解析阻塞。即使 configure 脚本本身没有显式的网络请求它调用的某些工具比如某些版本的 pkg-config可能会触发 DNS 查询。如果 DNS 服务器配置不当每次查询都要等好几秒才超时累积起来就非常可观。2.3 为什么等一等解决不了问题很多人遇到 checking 卡住第一反应是再等等可能机器慢。这个思路在大多数情况下是错的。本地编译检查再慢也就是毫秒到秒级别的差异。如果你等了一分钟以上还没有任何新输出那基本可以确定是网络阻塞而不是计算慢。网络阻塞的特点是进程处于不可中断的等待状态不会消耗 CPU也不会产生新的输出。你可以用top命令观察如果编译进程的 CPU 占用率接近 0%同时终端没有任何新行输出那几乎可以确定是卡在网络请求上了。注意有些 configure 脚本设置了很长的超时时间比如 120 秒甚至 300 秒。这意味着你可能要等好几分钟才能看到它跳过这个检查。与其干等不如主动干预。3. 定位卡点的实操方法别猜用工具看3.1 用 strace 精准定位阻塞位置遇到 checking 卡住最有效的排查工具是strace。它能跟踪进程的所有系统调用让你清楚看到进程到底卡在哪个操作上。操作步骤很简单。首先找到卡住的进程 PIDps aux | grep configure或者如果你是在另一个终端里操作可以直接用pgrep -f configure拿到 PID 之后用 strace 附加到该进程上sudo strace -p PID -f -e tracenetwork参数说明-p指定进程号-f跟踪子进程-e tracenetwork只显示网络相关的系统调用。如果进程卡在网络请求上你会看到类似这样的输出connect(3, {sa_familyAF_INET, sin_porthtons(80), sin_addrinet_addr(xxx.xxx.xxx.xxx)}, 16) -1 EINPROGRESS (Operation now in progress)这就说明进程正在尝试连接某个外部主机的 80 端口但连接没有成功返回。看到这个输出问题就确认了configure 脚本在等一个网络连接而这个连接在当前环境下无法建立。如果你没有安装 strace可以先装一下sudo apt install strace3.2 用 ltrace 查看库函数调用strace 看的是系统调用层面如果你想看更上层的信息比如进程在调用哪个库函数可以用ltracesudo ltrace -p PIDltrace 能显示进程调用的动态库函数比如getaddrinfo、connect等。如果看到进程反复调用getaddrinfo并且每次都返回失败那说明是 DNS 解析出了问题。3.3 用 timeout 命令给 configure 加超时保护与其等 configure 自己超时不如主动给它加一个时间限制。timeout命令可以做到这一点timeout 60 ./configure --prefix/usr/local这条命令的意思是给 configure 最多 60 秒的执行时间超过就强制终止。这样你就不用干等着了。如果 60 秒内 configure 没有完成说明确实有阻塞你可以根据前面 strace 的结果来针对性处理。3.4 查看 configure 脚本中的网络相关代码如果你想知道 configure 脚本里到底哪些地方会触发网络请求可以直接搜索脚本内容grep -n wget\|curl\|http\|ftp\|download configure这条命令会列出 configure 脚本中所有涉及网络操作的代码行。你可以根据行号定位到具体的检查逻辑判断这个检查是否必要。实操心得我一般会先用grep快速扫一遍 configure 脚本看看有没有明显的网络请求。如果有再决定是跳过这个检查还是配置代理。这个方法比 strace 更快适合在编译之前就做好预判。4. 六种解决方案从临时绕过到彻底修复4.1 方案一跳过网络检查最直接如果 configure 脚本中的网络检查不是必须的最直接的办法就是跳过它。具体怎么跳过取决于脚本的实现方式。方法 A设置环境变量。很多 configure 脚本会检查某个环境变量来决定是否执行网络请求。比如有些脚本会检查http_proxy变量如果设置了就尝试通过代理访问如果没设置就跳过。你可以尝试./configure --prefix/usr/local --disable-download或者NO_NETWORK1 ./configure --prefix/usr/local具体用哪个变量名需要看 configure 脚本的说明。你可以用./configure --help查看所有可用选项找到和网络相关的开关。方法 B直接修改 configure 脚本。如果脚本没有提供跳过选项你可以手动注释掉网络检查相关的代码。用文本编辑器打开 configure找到触发网络请求的那几行在前面加#注释掉。修改之前建议先备份cp configure configure.bak然后用vim或nano编辑。找到类似这样的代码块# 原始代码 if test $cross_compiling no; then $as_echo $as_me: checking for online resources 6 wget -q http://example.com/resource -O resource.txt fi把它改成# 修改后 if test $cross_compiling no; then $as_echo $as_me: skipping online resource check 6 # wget -q http://example.com/resource -O resource.txt fi这样脚本就会跳过网络请求直接继续后面的检查。注意修改 configure 脚本后如果后续执行了autoreconf或autoconf命令修改会被覆盖。所以修改后直接运行./configure和make不要再重新生成 configure 脚本。4.2 方案二配置本地缓存或离线资源如果网络检查是必须的但当前环境无法访问外网可以考虑提前把需要的资源下载到本地然后让 configure 脚本从本地读取。步骤一在能上网的机器上下载所需资源。根据 configure 脚本的提示确定它需要下载什么文件。通常是一个压缩包或者一个数据文件。步骤二把文件放到指定位置。把下载好的文件复制到源码目录下或者复制到 configure 脚本期望的路径。步骤三修改 configure 脚本指向本地文件。把脚本中的下载地址改成file://协议的本地路径# 原始代码 wget -q http://example.com/data.tar.gz -O data.tar.gz # 修改后 cp /path/to/local/data.tar.gz ./data.tar.gz这样脚本就不需要联网了。4.3 方案三设置合理的超时时间如果网络检查无法跳过但你知道它最终会超时并继续那可以缩短超时时间减少等待。很多网络工具都支持超时参数。比如wget可以用--timeout指定超时秒数curl可以用--connect-timeout和--max-time。如果 configure 脚本里用的是这些工具你可以通过环境变量或者修改脚本的方式缩短超时。以 wget 为例可以在脚本中找到 wget 调用加上超时参数# 原始代码 wget -q http://example.com/resource -O resource.txt # 修改后 wget -q --timeout5 --tries1 http://example.com/resource -O resource.txt这样即使网络不通5 秒后就会放弃不会一直卡着。4.4 方案四使用系统包管理器替代源码编译如果你编译这个软件的目的只是使用它而不是修改它的源码那最省事的方案是用 Ubuntu 的包管理器直接安装sudo apt install package-nameUbuntu 的官方仓库里有大量常用软件安装速度快依赖自动处理不需要手动编译。你可以先用apt search查一下有没有现成的包apt search keyword如果仓库里有直接安装就行完全绕过了编译环节。实操心得我见过很多人明明可以用apt install一行命令搞定的事情非要花几个小时从源码编译。除非你需要特定版本、特定编译选项或者需要修改源码否则优先用包管理器。4.5 方案五换用国内镜像源加速下载如果 configure 阶段的网络请求是下载依赖包而下载速度慢是因为源站在国外那可以换成国内镜像源。以常见的软件源为例Ubuntu 本身的 apt 源可以换成国内镜像sudo sed -i s/archive.ubuntu.com/mirrors.aliyun.com/g /etc/apt/sources.list sudo apt update对于 configure 脚本中调用的下载工具如果它支持指定镜像地址也可以通过环境变量或配置文件来切换。比如 pip 可以配置国内源pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple这样后续的下载就会走国内镜像速度快很多。4.6 方案六使用 ccache 加速重复编译虽然 ccache 不能解决 checking 卡住的问题但它能显著加速make阶段的编译速度。如果你需要反复编译同一个项目比如调试代码时ccache 可以把编译结果缓存起来下次编译时直接复用。安装 ccachesudo apt install ccache然后在 configure 时指定使用 ccache./configure CCccache gcc CXXccache g或者在~/.bashrc里添加export CCccache gcc export CXXccache g这样每次编译时ccache 会先检查缓存如果之前编译过相同的代码就直接返回缓存结果省去重复编译的时间。5. 常见问题速查与排查技巧5.1 常见问题对照表现象可能原因排查方法解决方案configure 卡在 checking for gcc编译器未安装或路径不对which gcc检查sudo apt install build-essentialconfigure 卡在 checking for xxx library依赖库缺失dpkg -lgrep xxxconfigure 卡在 checking for online resources网络请求阻塞strace -p PID -e tracenetwork跳过检查或配置本地资源configure 卡在 checking whether to build xxx脚本逻辑死循环查看 configure 脚本对应行修改脚本或换版本make 阶段报错找不到头文件开发包未安装查看报错信息中的头文件名apt install libxxx-devmake 阶段编译极慢单线程编译nproc查看核心数make -j$(nproc)make install 权限不足未使用 sudo查看报错信息sudo make install5.2 排查思路从外到内逐层定位遇到编译问题我习惯按这个顺序排查第一层确认基础工具链是否完整。运行gcc --version、make --version、pkg-config --version确保这些基础工具都装了。Ubuntu 上一条命令搞定sudo apt install build-essential pkg-config第二层确认依赖库是否齐全。查看项目文档中的依赖列表逐个确认是否安装。可以用dpkg -l检查已安装的包用apt-cache search查找可用的包。第三层确认网络环境是否正常。如果前面两层都没问题但 configure 还是卡住那大概率是网络问题。用 strace 确认阻塞位置然后按第 4 节的方案处理。第四层确认 configure 脚本本身是否有 bug。极少数情况下configure 脚本本身存在逻辑错误导致在某些环境下死循环。这种情况可以尝试换一个版本的源码或者去项目的 issue 列表里搜索是否有类似问题。5.3 独家避坑技巧技巧一编译前先读 README 和 INSTALL 文件。很多项目会在这些文件里说明编译依赖和特殊配置提前读一遍能避免很多弯路。技巧二用script命令记录编译过程。编译出错时完整的日志非常重要。用script命令可以把终端输出保存到文件script build.log ./configure make exit这样所有输出都会记录在build.log里方便事后排查。技巧三在 screen 或 tmux 里编译。编译大项目可能耗时很长如果 SSH 连接断开编译进程会被终止。用 screen 或 tmux 可以保持会话tmux new -s build ./configure make # 按 CtrlB 然后按 D 脱离会话 # 下次用 tmux attach -t build 重新连接技巧四用make -j并行编译。现代机器通常有多个 CPU 核心用-j参数可以并行编译大幅缩短时间make -j$(nproc)$(nproc)会自动获取 CPU 核心数。不过要注意并行编译有时会因为依赖顺序问题导致报错如果遇到奇怪的编译错误可以试试单线程编译确认是否是并行导致的问题。技巧五保留 configure 的缓存文件。configure 脚本会生成一个config.cache文件记录上次检查的结果。如果你需要多次运行 configure保留这个文件可以跳过重复检查加快速度。不过如果环境发生了变化建议删掉缓存重新检查rm config.cache ./configure6. 一个完整的实操案例6.1 场景描述假设你在一台 Ubuntu 机器上编译一个名为libimageproc的图像处理库。这台机器可以访问内网但无法直接访问外网。你执行了以下命令tar -xzf libimageproc-2.1.0.tar.gz cd libimageproc-2.1.0 ./configure --prefix/usr/local终端输出停在checking for gcc... gcc checking whether the C compiler works... yes checking for online model data...然后就一直卡在这里等了十分钟没有任何新输出。6.2 排查过程第一步确认进程状态。ps aux | grep configure输出显示 configure 进程存在CPU 占用率 0.0%状态为S睡眠。第二步用 strace 定位阻塞点。sudo strace -p PID -e tracenetwork输出显示connect(3, {sa_familyAF_INET, sin_porthtons(443), sin_addrinet_addr(203.0.113.10)}, 16) -1 EINPROGRESS确认进程正在尝试连接一个外部 IP 的 443 端口但连接无法建立。第三步查看 configure 脚本中的相关代码。grep -n online model data configure找到对应的代码行$as_echo $as_me: checking for online model data 6 wget -q https://example.com/models/model-data.tar.gz -O model-data.tar.gz确认是 wget 在下载模型数据文件。6.3 解决方案实施方案选择由于模型数据文件是编译所必需的不能简单跳过。我们采用本地缓存 修改脚本的方案。步骤一在能上网的机器上下载模型数据文件。wget https://example.com/models/model-data.tar.gz步骤二把文件传输到编译机器上。可以用 scp 或者 U 盘拷贝放到源码目录下。步骤三修改 configure 脚本跳过下载步骤。cp configure configure.bak vim configure找到 wget 那一行改成# 原始代码 wget -q https://example.com/models/model-data.tar.gz -O model-data.tar.gz # 修改后 if [ ! -f model-data.tar.gz ]; then echo Error: model-data.tar.gz not found 2 exit 1 fi步骤四重新运行 configure。./configure --prefix/usr/local这次 configure 顺利通过不再卡住。步骤五编译并安装。make -j$(nproc) sudo make install6.4 经验总结这个案例的关键在于先定位再解决。不要一上来就盲目尝试各种方法而是用 strace 确认阻塞位置然后针对性地处理。另外修改 configure 脚本之前一定要备份万一改错了可以快速恢复。提示如果你经常需要在离线环境下编译各种软件建议搭建一个内网的软件源镜像把常用的依赖包和资源文件都缓存到内网。这样后续编译时就不需要每次都手动处理网络问题了。7. 预防措施让下次编译不再卡7.1 编译前的环境检查清单在开始编译之前花两分钟做以下检查可以避免大部分问题确认build-essential已安装dpkg -l build-essential确认pkg-config已安装pkg-config --version确认网络环境ping -c 1 8.8.8.8如果无法访问外网提前做好离线准备确认磁盘空间充足df -h确认源码目录权限正确ls -la阅读项目文档中的编译说明7.2 建立本地编译环境的最佳实践如果你经常需要从源码编译软件建议把编译环境标准化统一安装基础工具链sudo apt install build-essential pkg-config cmake autoconf automake libtool ccache配置 ccache 加速重复编译echo export CCccache gcc ~/.bashrc echo export CXXccache g ~/.bashrc source ~/.bashrc建立本地依赖库缓存目录mkdir -p ~/build-cache把常用的依赖库源码包和资源文件放在这个目录里需要时直接从本地取。使用构建脚本自动化流程对于经常编译的项目可以写一个简单的构建脚本#!/bin/bash set -e PREFIX/usr/local JOBS$(nproc) echo Configuring... ./configure --prefix$PREFIX echo Building with $JOBS jobs... make -j$JOBS echo Installing... sudo make install echo Done.把脚本保存为build.sh每次编译时直接运行bash build.sh就行。7.3 长期维护建议源码编译不是一次性工作后续升级版本时还要重复整个流程。为了减少重复劳动可以考虑把编译好的软件打包成 deb 包方便在多台机器上部署用 Docker 容器封装编译环境确保环境一致性记录每次编译的配置参数和遇到的问题形成自己的知识库我个人在实际操作中的体会是编译问题的排查成本远高于预防成本。花十分钟提前检查环境比花一个小时排查卡住的原因要划算得多。尤其是网络相关的检查在编译之前用grep扫一遍 configure 脚本看看有没有网络请求能省下大量等待时间。最后再分享一个小技巧如果你不确定某个 configure 脚本会不会卡住可以先用timeout 30 ./configure --help试一下。--help参数通常不会触发完整的检查流程但如果连--help都卡住那说明脚本本身有问题需要直接查看脚本内容。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑