編譯通過的C程序調用libhdfs寫入文件,運行時報錯:
Exception: Mkdirs failed to create /my Call to FileSystem::create failed! Failed to open /my/t.txt for writing!
# 普通用戶無權在HDFS根目錄創建目錄 $ ./test # 解決:sudo提權 $ sudo ./test
$ sudo ./test Environment variable CLASSPATH not set! # libhdfs依賴CLASSPATH找jar包 Failed to open /my/txt for writing!
原因:/etc/sudoers默認Defaults env_reset清理環境變量。
修復:編輯sudo visudo,修改:
Defaults env_reset → Defaults !env_reset
或精確保留:Defaults env_keep += "CLASSPATH JAVA_HOME HADOOP_HOME"
$ sudo chmod 777 /etc/sudoers # 錯誤!修改權限破壞sudoers $ sudo chmod 440 /etc/sudoers sudo: /etc/sudoers 模式為 0777,應為 0440 sudo: 無法初始化策略插件
救援方案:
su root(需知道root密碼)chmod sudoers,只用visudo編輯# /etc/profile.d/hadoop.sh —— 所有用戶登入生效 export JAVA_HOME=/usr/lib/jvm/java-8-openjdk export HADOOP_HOME=/usr/local/hadoop export CLASSPATH=$($HADOOP_HOME/bin/hadoop classpath --glob) export LD_LIBRARY_PATH=$HADOOP_HOME/lib/native:$LD_LIBRARY_PATH # /etc/sudoers.d/hadoop —— 精確保留變量 Defaults env_keep += "JAVA_HOME HADOOP_HOME CLASSPATH LD_LIBRARY_PATH"
// 啟動時檢查關鍵環境變量
const char *required[] = {"JAVA_HOME", "CLASSPATH", "HADOOP_HOME"};
for (int i = 0; i < 3; ++i) {
if (!getenv(required[i])) {
fprintf(stderr, "FATAL: Missing env %s\n", required[i]);
exit(EXIT_FAILURE);
}
}
// HDFS操作錯誤碼檢查
hdfsFS fs = hdfsConnect("default", 0);
if (!fs) {
fprintf(stderr, "hdfsConnect failed: %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
| 層面 | 建議 |
|---|---|
| 部署 | 系統級環境變量 + sudoers精確保留 |
| 開發 | C代碼啟動自檢環境變量 |
| 運行 | 專用服務用戶 + systemd管理,避免sudo |
| 權限 | HDFS ACL配置目錄寫入權限,而非依賴root |
| 維護 | 絕不手動chmod sudoers,只用visudo |