start-dfs脚本启动NameNode过程

start-dfs.sh:从代码的注释上看,这个代码文件可以分为几个部分:NameNode启动前的环境配置工作、NameNode启动、DataNode启动、Secondary NameNode启动、quorumjournal node启动、ZKFC启动。
在启动前的环境配置工作中,这段代码调用了另一个脚本“hdfs-config.sh"。

if [[ -f "${HADOOP_LIBEXEC_DIR}/hdfs-config.sh" ]]; then
  . "${HADOOP_LIBEXEC_DIR}/hdfs-config.sh"

hdfs-config.sh在export了很多变量后它又调用了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"

转到hadoop-config.sh,这个脚本又会调用hadoop-functions.sh。之后hadoop-config.sh执行了很多在hadoop-functions.sh里定义的函数,这些函数完成了环境配置的工作(例如设置HADOOP_XXX_HOME等环境变量、执行shell profile文件的配置等等),在这里不作分析。
hadoo-functions.sh这个文件非常重要,因为这个文件定义了很多要被用到的函数。
回到start-dfs.sh,可以观察到启动NameNode、DataNode、SecondaryNameNode、JournalNode、ZKFC的代码都相当一致,其核心都是调用hadoop_uservar_su函数。

hadoop_uservar_su hdfs namenode "${HADOOP_HDFS_HOME}/bin/hdfs" \
    --workers \
    --config "${HADOOP_CONF_DIR}" \
    --hostnames "${NAMENODES}" \
    --daemon start \
    namenode ${nameStartOpt}

HADOOP_HDFS_HOME在hdfs-config.sh里设置,其值就是HADOOP_HOME的值;NAMENODES在这段代码之前被设置,由./bin/hdfs getconf -namenodes查询,如果没有则设置为$(hostname);至于nameStartOpt,要是运行start-dfs.sh时没有带任何参数则为其值为空。

hadoop_uservar_su定义在hadoop-functions.sh:

## @description  Execute a command via su when running as root
## @description  with extra support for commands that might
## @description  legitimately start as root (e.g., datanode)
function hadoop_uservar_su{
	...
	if hadoop_privilege_check; then
		hadoop_su "${!uvar}" "$@"
	else
    	"$@"
	...
}

实际上就是和用户权限相关的操作,hadoop_privilege_check就是检查是否运行在root权限。但不管用户权限如何,最终都要运行"$@“,$@的值就是参数列表,”$@"就会把参数作为命令运行。所以上文调用hadoop_uservar_su最终会调用(以本机为例):

hdfs --workers \
    --config "${HADOOP_HOME}/etc/hadoop" \
    --hostnames "localhost" \
    --daemon start \
    namenode 

hdfs也是个脚本文件。hdfs会调用hdfs-config.sh,而后者会调用hadoop-config.sh。不同于之前没带参数时调用hadoop-config.sh,此次调用一共有8个参数,它们都会传递给hadoop_parse_args函数,最后只有一个剩下了,即是namenode。不过在调用hadoop_parse_args之前,会用变量HADOOP_USER_PARAMS把所有参数保存起来,因为后面会用到。

#hadoop-config.sh
HADOOP_USER_PARAMS=("$@")
hadoop_parse_args "$@"

#hadoop-functions.sh
function hadoop_parse_args
  while true; do
  case $1 in      
  --config)
    shift
    confdir=$1
    shift
    ...	
    if [[ -d "${confdir}" ]]; then
      HADOOP_CONF_DIR="${confdir}"
  --daemon)
    shift
    HADOOP_DAEMON_MODE=$1
    shift
  --hostnames)
    shift
    HADOOP_WORKER_NAMES="$1"
    shift
  --workers)
    shift    
    HADOOP_WORKER_MODE=true

这里设置了一些变量,像HADOOP_DAEMON_MODE用来区分是start还是stop NameNode,HADOOP_WORKER_MODE在后面也会决定代码分支。
之后控制流就回到hdfs上

#hdfs
  HADOOP_SUBCMD=$1
  shift
  HADOOP_SUBCMD_ARGS=("$@")	
  hdfscmd_case "${HADOOP_SUBCMD}" "${HADOOP_SUBCMD_ARGS[@]}"

由于参数只剩下namenode了,所以HADOOP_SUBCMD的值是namenode,而HADOOP_SUBCMD_ARGS为空值
hdfscmd_case就定义在hdfs中:

function hdfscmd_case
  case ${subcmd} in
  namenode)
    HADOOP_SUBCMD_SUPPORTDAEMONIZATION="true"
    HADOOP_CLASSNAME='org.apache.hadoop.hdfs.server.namenode.NameNode'
    hadoop_add_param HADOOP_OPTS hdfs.audit.logger "-Dhdfs.audit.logger=${HDFS_AUDIT_LOGGER}"

可以看到这个函数又设置了一些变量,其中重要的是设置了HADOOP_CLASSNAME。
之后的调用:

#hdfs
if [[ ${HADOOP_WORKER_MODE} = true ]]; then
  hadoop_common_worker_mode_execute "${HADOOP_HDFS_HOME}/bin/hdfs" "${HADOOP_USER_PARAMS[@]}"

#hadoop-functions.sh
function hadoop_common_worker_mode_execute
  hadoop_connect_to_hosts -- "${argv[@]}"

#hadoop-functions.sh
function hadoop_connect_to_hosts 
tmpslvnames=$(echo ${HADOOP_WORKER_NAMES} | tr -s ' ' ,)
      PDSH_SSH_ARGS_APPEND="${HADOOP_SSH_OPTS}" pdsh \
        -f "${HADOOP_SSH_PARALLEL}" \
        -w "${tmpslvnames}" $"${@// /\\ }" 2>&1  

可以看到最后会调用pdsh,pdsh会在远程目标主机执行操作。在我的机器里pdsh的调用参数,HADOOP_SSH_PARALLEL的值是10,tmpslvnames的值是localhost,$“${@// /\ }“的值是”-- $HADOOP_HOME/bin/hdfs --config $HADOOP_HOME/etc/hadoop --daemon start namenode”
此时在本地shell脚本的执行在打开pdsh后函数返回后就结束了,之后的操作交由远程主机(我这里是localhost)继续处理。
远程主机将运行hdfs,而参数为"–config $HADOOP_HOME/etc/hadoop --daemon start namenode",与之前的hdfs调用最大的不同是没了–workers参数,所以脚本不会调用hadoop_common_worker_mode_execute,而是hadoop_generic_java_subcmd_handler:

#hdfs
# everything is in globals at this point, so call the generic handler
hadoop_generic_java_subcmd_handler

#hadoo-functions.sh
function hadoop_generic_java_subcmd_handler
 if [[ "${HADOOP_SUBCMD_SUPPORTDAEMONIZATION}" = true ]]; then
    if [[ "${HADOOP_SUBCMD_SECURESERVICE}" = true ]]; then
	...
	else
      hadoop_daemon_handler \
        "${HADOOP_DAEMON_MODE}" \
        "${HADOOP_SUBCMD}" \
        "${HADOOP_CLASSNAME}" \
        "${daemon_pidfile}" \
        "${daemon_outfile}" \
        "${HADOOP_SUBCMD_ARGS[@]}"

这里的参数分别为,HADOOP_DAEMON_MODE=start,HADOOP_SUBCMD=namenode,HADOOP_CLASSNAME=org.apache.hadoop.hdfs.server.namenode.NameNode,而剩下两个参数由机器自行得出,HADOOP_SUBCMD_ARGS为空。

function hadoop_daemon_handler
  case ${daemonmode} in
    start|default)
	...
	hadoop_start_daemon_wrapper "${daemonname}" \
        "${class}" "${daemon_pidfile}" "${daemon_outfile}" "$@"
	//前两个参数分别为namenode, org.apache.hadoop.hdfs.server.namenode.NameNode
	
function hadoop_start_daemon_wrapper
  hadoop_start_daemon "${daemonname}" \
    "$class" \
    "${pidfile}" \
    "$@" >> "${outfile}" 2>&1 < /dev/null &
    (( counter=0 ))

function hadoop_start_daemon
  exec "${JAVA}" "-Dproc_${command}" ${HADOOP_OPTS} "${class}" "$@"

最后执行运行java,使用选项"-Dproc_namenode",class为"org.apache.hadoop.hdfs.server.namenode.NameNode",HADOOP_OPTS有一长串,$@为pid文件。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值