本次安装的是3.1.5版本hadoop的伪分布式,按照官方的指导手册quickly start进行出现了JAVA_HOME无法找到的问题
sirius@sirius:~/hadoop$ sbin/start-dfs.sh
Starting namenodes on [localhost]
localhost: ERROR: JAVA_HOME is not set and could not be found.
Starting datanodes
localhost: ERROR: JAVA_HOME is not set and could not be found.
Starting secondary namenodes [sirius]
sirius: ERROR: JAVA_HOME is not set and could not be found.
发现程序使用ssh远程执行了三个脚本
ssh -o BatchMode=yes -o StrictHostKeyChecking=no -o ConnectTimeout=10s localhost -- /home/sirius/hadoop/bin/hdfs --config /home/sirius/hadoop/etc/hadoop --daemon start namenode
ssh -o BatchMode=yes -o StrictHostKeyChecking=no -o ConnectTimeout=10s localhost -- /home/sirius/hadoop/bin/hdfs --config /home/sirius/hadoop/etc/hadoop --daemon start datanode
ssh -o BatchMode=yes -o StrictHostKeyChecking=no -o ConnectTimeout=10s sirius -- /home/sirius/hadoop/bin/hdfs --config /home/sirius/hadoop/etc/hadoop --daemon start secondarynamenode
验证确实使用ssh缺少环境变量
sirius@sirius:~/hadoop$ ssh localhost 'echo $JAVA_HOME'
sirius@sirius:~/hadoop$ echo $JAVA_HOME
/usr/local/openjdk
网上查了资料说是这种是使用非交互式非登录使用shell,会去加载~/.bashrc 文件,所以需要在~/.bashrc中也添加环境变量
而我在/etc/bashrc, /etc/bashrc.bash, ~/.bashrc的末尾都添加了环境变量,依旧无法正确读取
参考博客服务器远程执行脚本无法获取环境变量的问题
得到原因:普通用户的bashrc的开始有一个判断
case $- in
*i*) ;;
*) return;;
esac
这个判断会导致后续的代码无法正确执行,所以需要将环境变量添加至这个判断之前。
从配置文件中解决感觉不太优雅,还是从脚本中解决这个问题
报错均来自远程执行hdfs脚本,在hdfs脚本中调用了hdfs-config.sh脚本
...
if [[ -f "${HADOOP_LIBEXEC_DIR}/hdfs-config.sh" ]]; then
# shellcheck source=./hadoop-hdfs-project/hadoop-hdfs/src/main/bin/hdfs-config.sh
. "${HADOOP_LIBEXEC_DIR}/hdfs-config.sh"
else
echo "ERROR: Cannot execute ${HADOOP_LIBEXEC_DIR}/hdfs-config.sh." 2>&1
exit 1
fi
...
而在hdfs-config.sh中,实际是调用hadoop-config.sh完成实际的业务
...
if [[ -n "${HADOOP_COMMON_HOME}" ]] &&
[[ -e "${HADOOP_COMMON_HOME}/libexec/hadoop-config.sh" ]]; then
. "${HADOOP_COMMON_HOME}/libexec/hadoop-config.sh"
elif [[ -e "${HADOOP_LIBEXEC_DIR}/hadoop-config.sh" ]]; then
. "${HADOOP_LIBEXEC_DIR}/hadoop-config.sh"
elif [ -e "${HADOOP_HOME}/libexec/hadoop-config.sh" ]; then
. "${HADOOP_HOME}/libexec/hadoop-config.sh"
else
echo "ERROR: Hadoop common not found." 2>&1
exit 1
fi
...
在hadoop-config.sh中调用了函数hadoop_exec_hadoopenv完成环境变量的配置
...
hadoop_find_confdir
hadoop_exec_hadoopenv
hadoop_import_shellprofiles
hadoop_exec_userfuncs
...
在hadoop-functions.sh的hadoop_exec_hadoopenv函数中
function hadoop_exec_hadoopenv
{
if [[ -z "${HADOOP_ENV_PROCESSED}" ]]; then
if [[ -f "${HADOOP_CONF_DIR}/hadoop-env.sh" ]]; then
export HADOOP_ENV_PROCESSED=true
. "${HADOOP_CONF_DIR}/hadoop-env.sh"
fi
fi
}
由此可见只需要更改hadoop-env.sh, 在这里增加环境变量,就可以使得ssh远程执行脚本也具有环境变量了