目录
目的
1.Hadoop服务实际上是使用Java命令识别/运行Main类,启动进程,而JAVA如何识别Hadoop相关jar路径呢?
2.Hadoop提供多个*-env.sh文件,我们通常在这些文件中修改/定义环境变量来修改进程参数,而Hadoop相关配置如何传入,在哪个文件中配置真正会影响到Hadoop进程参数呢(配置文件优先级)?
本文梳理脚本链路,理清进程启动脚本时配置文件/函数加载情况(以RM服务为例)
Hadoop启动配置遵循如下规则,当变量赋值后,就不会轻易修改,也就是正常情况下后面的变量不会去覆盖之前变量值(
如果变量A是过期变量B的代替变量,而B有值,则会覆盖A值)
hadoop-env.sh是所有组件都会用到!!!我们可以在该文件中配置通用参数,在子组件配置文件(子组件-env.sh)定特定参数
接下来直接看脚本流程
Hadoop3.x版本Shell script rewrite,将很多杂乱环境变量统一管理,将冗余代码使用函数的形式重复调用,将这些冗余操作移到了${HADOOP_HOME}/libexec/hadoop-functions.sh中
使用启动命令启动hadoop组件,以resouremanager服务为例子
0.启动脚本${HADOOP_HOME}/bin/yarn
1.执行yarn-config.sh,该脚本中执行hadoop-config.sh
hadoop-config.sh
# 加载了函数库,hadoop组件启动需要使用到
.hadoop-functions.sh
# 配置了hadoop相关路径/jar
hadoop_bootstrap
# 配置conf路径
hadoop_find_confdir
# 配置hadoop-env.sh路径
hadoop_exec_hadoopenv
# 加载${HADOOP_LIBEXEC_DIR}/shellprofile.d/*.sh和${HADOOP_CONF_DIR}/shellprofile.d/*.sh
hadoop_import_shellprofiles
# 加载${HADOOP_CONF_DIR}/hadoop-user-functions.sh用来覆盖hadoop-functions.sh的函数
hadoop_exec_userfuncs
# 加载${HOME}/.hadoop-env
hadoop_exec_user_hadoopenv
# 验证${HADOOP_CONF_DIR}/log4j.properties是否存在
hadoop_verify_confdir
# 根据不同操作系统进行配置
hadoop_os_tricks
# 验证JAVA_HOME存在/验证java可执行
hadoop_java_setup
# 初始化CLASSPATH/HADOOP一些参数
hadoop_basic_init
# 加载yarn-env.sh,包含多个判断过期参数是否存在的函数,如果存在会将值赋值给代替的新参数并提醒参数过期了
hadoop_subproject_init
# 加载_[hdfs|yarn|mapred]_hadoop_init函数(在${HADOOP_LIBEXEC_DIR}/shellprofile.d/hadoop-[hdfs|yarn|mapred].sh)
hadoop_shellprofiles_init
# 添加配置到JAVA_LIBRARY_PATH变量
hadoop_add_javalibpath "${HADOOP_HOME}/build/native"
hadoop_add_javalibpath "${HADOOP_HOME}/${HADOOP_COMMON_LIB_NATIVE_DIR}"
# 加载_[hdfs|yarn|mapred]_hadoop_nativelib函数
hadoop_shellprofiles_nativelib
# 添加commom相关参数到classpath变量
hadoop_add_common_to_classpath
# 加载_[hdfs|yarn|mapred]_hadoop_classpath函数(在${HADOOP_LIBEXEC_DIR}/shellprofile.d/hadoop-[hdfs|yarn|mapred].sh),是添加相关组件的jar包路径
hadoop_shellprofiles_classpath
# 执行${HOME}/.hadooprc,如果存在的话
hadoop_exec_hadooprc
至此yarn-config.sh/hadoop-config.sh执行完毕
2.继续yarn脚本
# 验证是否允许${USER}执行给定的子命令,创建了命令YARN_RESOURCEMANAGER_USER
hadoop_verify_user_perm
# yarn脚本function,Default command handler for yarn command,以rm为例子,将"$HADOOP_YARN_HOME/$YARN_DIR/timelineservice/*相关添加到classpath/设置HADOOP_CLASSNAME/
yarncmd_case
# 如果在window系统下,路径转window格式
hadoop_translate_cygwin_path
# 添加sld(hadoop路径)到HADOOP_OPTS参数中
hadoop_add_param
# 添加HADOOP_CLIENT_OPTS给HADOOP_OPTS
hadoop_add_client_opts
# 添加(program)_(command)_OPTS to HADOOP_OPTS,例如添加YARN_RESOURCEMANAGER_OPTS
hadoop_subcommand_opts
# yarn脚本的最后一个函数,接下来看下这个function的逻辑
hadoop_generic_java_subcmd_handler
3.hadoop_generic_java_subcmd_handler
# 检测HADOOP_SECURE_CLASSNAME是否有定义
hadoop_detect_priv_subcmd
# 定义HADOOP_ROOT_LOGGER/HADOOP_LOGFILE
# 配置添加,包含多个函数
hadoop_finalize
4.hadoop_finalize
# 将配置添加到classpath之前
hadoop_add_classpath "${HADOOP_CONF_DIR}" before
# 将HADOOP_CLASSPATH添加到classpath之后
hadoop_add_to_classpath_userpath
# 如果是window转路径格式
hadoop_translate_cygwin_path CLASSPATH true
# 添加java.library.path给HADOOP_OPTS
hadoop_finalize_libpaths
# 添加内存配置给HADOOP_OPTS
hadoop_finalize_hadoop_heap
# 添加hadoop相关参数给HADOOP_OPTS (-Dhadoop.log.dir等)
hadoop_finalize_hadoop_opts
hadoop_finalize结束
5.回到hadoop_generic_java_subcmd_handler
# 准备启动进程,hadoop_generic_java_subcmd_handler结束
hadoop_daemon_handler
6.hadoop_daemon_handler 启动
# 验证是否能创建pid目录
hadoop_verify_piddir
# 验证是否能创建log目录
hadoop_verify_logdir
# 查看是否有pid对应的进程根据不同操作进行返回
hadoop_status_daemon "${daemon_pidfile}"
# 启动封装,包含多个函数
hadoop_start_daemon_wrapper
# 启动一次进程,生成一个out文件,mv其他out文件
hadoop_rotate_log
# 实际启动进程,函数中export CLASSPATH将CLASSPATH变量暴露出去,后续执行exec "${JAVA}" "-Dproc_${command}" ${HADOOP_OPTS} "${class}" "$@",java读取CLASSPATH变量知道hadoop的相关jar在哪,所以hadoop相应类可以被找到,从而启动服务
hadoop_start_daemon
# 后面还有其他的一些disown等等