CentOS 6.7 上消除 Hadoop “Unable to load native-hadoop library” 警告:从定位到编译替换一条龙
环境:CentOS 6.7(glibc 2.12)、Hadoop 2.6.5
目标:消除执行hadoop fs ...时出现的警告:WARN util.NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable
1. 问题现象
在创建 HDFS 目录时:
hadoop fs -mkdir /myhive2
出现警告:
WARN util.NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable
这个警告的含义是:Hadoop 没有成功加载 native(C/C++)库,于是退回到纯 Java 实现。
2. 初步判断:native 库到底有没有?
先看 $HADOOP_HOME/lib/native:
ls -l $HADOOP_HOME/lib/native
我这边能看到:
libhadoop.so -> libhadoop.so.1.0.0libhdfs.so -> libhdfs.so.0.0.0
说明 库文件本身存在,但仍然无法加载,问题大概率在:
JVM/动态链接器找不到库或依赖
库和系统不兼容(最典型:glibc 版本不匹配)
3. 关键定位:ldd 报 GLIBC 版本不满足
我用 ldd 检查 libhadoop.so:
ldd $HADOOP_HOME/lib/native/libhadoop.so.1.0.0 | egrep "not found|GLIBC"
得到致命信息:
/lib64/libc.so.6: version `GLIBC_2.14' not found
这就说明:当前 libhadoop.so 是在需要 glibc 2.14 的系统上编译的,而我这台机器是 CentOS 6.7,glibc 版本更低。
4. 进一步确认:系统 glibc 版本是多少?
cat /etc/redhat-release
ldd --version | head -n 1
输出:
CentOS release 6.7 (Final)
glibc 2.12
再看系统实际提供的符号版本:
strings /lib64/libc.so.6 | grep -E 'GLIBC_2\.(1[0-2])' | tail
结果包含 GLIBC_2.10/2.11/2.12,但 没有 GLIBC_2.14。
这也解释了一个常见误区:
yum update glibc只能更新 2.12 的 release(修补版),并不会把 CentOS 6 的 glibc 升到 2.14。
5. 解决思路:让 native 库在本系统上可用
既然核心矛盾是 glibc 不兼容,那解决方案就很清晰:
✅ 推荐:在 CentOS 6.7 上重新编译 Hadoop 2.6.5 native(生成只依赖 GLIBC_2.12 的
.so)✅ 或者:直接找一套在 CentOS 6 上编译好的 native 目录替换
❌ 不推荐:强行升级系统 glibc 到 2.14(风险极高,可能把系统“地基”搞崩)
我选择了 重新编译 Hadoop 2.6.5 的 native。
6. 重新编译 Hadoop native:过程中的坑与修复
6.1 先装 Maven(CentOS 6 默认源没有 maven)
我手头有 apache-maven-3.6.3-bin.zip,安装方式如下:
yum -y install unzip
mkdir -p /opt
cd /opt
unzip -q /root/apache-maven-3.6.3-bin.zip
ln -sfn /opt/apache-maven-3.6.3 /opt/maven
cat >/etc/profile.d/maven.sh <<'EOF'
export MAVEN_HOME=/opt/maven
export PATH=$MAVEN_HOME/bin:$PATH
EOF
source /etc/profile.d/maven.sh
mvn -version
6.2 Javadoc 构建失败:直接跳过
用 JDK8 构建 Hadoop 2.6.5 时,hadoop-annotations 会因为 javadoc HTML 更严格而失败。解决办法:跳过 javadoc。
mvn -Pdist,native -DskipTests -Dtar -Dmaven.javadoc.skip=true clean package
6.3 下载依赖“卡住”:配置 Maven 镜像
构建过程中会下载大量依赖,我用阿里云 Maven 镜像加速(注意必须有 <settings> 根节点):
~/.m2/settings.xml:
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 https://maven.apache.org/xsd/settings-1.0.0.xsd">
<mirrors>
<mirror>
<id>aliyunmaven</id>
<mirrorOf>*</mirrorOf>
<url>https://maven.aliyun.com/repository/public</url>
</mirror>
</mirrors>
</settings>
6.4 protoc 缺失:手动编译 protobuf 2.5.0
构建失败提示:
Cannot run program "protoc": No such file or directory
CentOS 6 的源里也没有 protobuf-compiler,于是我选择编译安装 protobuf 2.5.0(带 protoc):
# 解压源码 protobuf-2.5.0.tar.gz 后
cd protobuf-2.5.0
./configure --prefix=/usr/local
make -j$(nproc)
make install
ldconfig
/usr/local/bin/protoc --version
并确保 /usr/local/bin 在 PATH:
echo 'export PATH=/usr/local/bin:$PATH' >/etc/profile.d/localbin.sh
source /etc/profile.d/localbin.sh
6.5 Ant 下载 Tomcat 反复卡:手动放置到 downloads 目录
构建过程中(KMS/HttpFS)会通过 Ant <get> 下载 Tomcat 6.0.41:
hadoop-common-project/hadoop-kms/downloads/hadoop-hdfs-project/hadoop-hdfs-httpfs/downloads/
这两个目录是分开的,所以会“下载两次”。做法是 手动下载一次,然后软链接/复制到另一个目录。
7. 找到新编译的 native 库并验证 GLIBC 版本
编译完成后我用 find 定位 libhadoop.so:
cd /root/hadoop-2.6.5-src
find . -name 'libhadoop.so*' -o -name 'libhdfs.so*' | head -n 50
最终选择发行版目录里的这份:
./hadoop-dist/target/hadoop-2.6.5/lib/native/libhadoop.so.1.0.0
验证其依赖的 GLIBC:
strings ./hadoop-dist/target/hadoop-2.6.5/lib/native/libhadoop.so.1.0.0 \
| grep GLIBC_ | sort -V | tail -n 10
输出最高只有:
GLIBC_2.12
✅ 这正是我需要的(兼容 CentOS 6.7)。
8. 替换现网 Hadoop 的 native 并验证
8.1 备份并替换
export HADOOP_HOME=/usr/local/hadoop-2.6.5
mv $HADOOP_HOME/lib/native $HADOOP_HOME/lib/native.bak.$(date +%F)
mkdir -p $HADOOP_HOME/lib/native
cp -a /root/hadoop-2.6.5-src/hadoop-dist/target/hadoop-2.6.5/lib/native/* \
$HADOOP_HOME/lib/native/
echo "$HADOOP_HOME/lib/native" > /etc/ld.so.conf.d/hadoop.conf
ldconfig
确保 hadoop-env.sh 里有:
export HADOOP_COMMON_LIB_NATIVE_DIR=$HADOOP_HOME/lib/native
export HADOOP_OPTS="$HADOOP_OPTS -Djava.library.path=$HADOOP_HOME/lib/native"
8.2 验证 native 已加载
hadoop checknative -a
看到关键行:
hadoop: true /usr/local/hadoop-2.6.5/lib/native/libhadoop.so.1.0.0
snappy: true ...
zlib: true ...
openssl: true ...
再执行:
hadoop fs -mkdir /myhive2
不再出现 NativeCodeLoader 警告(如果目录已存在则提示 File exists 属正常行为)。
9. 分发到多台 slave(只同步 native,避免覆盖配置)
为了让集群其他节点也不再告警,我采用“只分发 native”方案:
master 上打包并 scp
cd /usr/local/hadoop-2.6.5
tar czf /tmp/hadoop-2.6.5-native-centos6.tgz -C lib native
for h in slave1 slave2 slave3; do
scp /tmp/hadoop-2.6.5-native-centos6.tgz root@$h:/tmp/
done
每台 slave 上替换并验证
HADOOP_HOME=/usr/local/hadoop-2.6.5
mv $HADOOP_HOME/lib/native $HADOOP_HOME/lib/native.bak.$(date +%F_%H%M%S)
tar xzf /tmp/hadoop-2.6.5-native-centos6.tgz -C $HADOOP_HOME/lib
echo "$HADOOP_HOME/lib/native" > /etc/ld.so.conf.d/hadoop.conf
ldconfig
$HADOOP_HOME/bin/hadoop checknative -a
10. 总结
这次问题的核心不是“没有 lib/native 文件”,而是:
native 库与系统 glibc 不兼容(
GLIBC_2.14 not found)CentOS 6 只能稳定提供 glibc 2.12,所以必须:
换一份在 CentOS 6 上编译的 native
或在本机重新编译(最终我选择了这条)
最终效果:
hadoop checknative -a显示hadoop: truehadoop fs ...不再出现NativeCodeLoaderWARN分发到 slave 后全节点一致生效
如果你也在 CentOS 6 上折腾 Hadoop native,建议直接记住一句话:
遇到
GLIBC_x.y not found,别纠结 Hadoop 配置,先确认 native 库是在哪个系统上编译的。