设为首页 收藏本站
查看: 1700|回复: 0

[经验分享] Hadoop启动脚本分析

[复制链接]

尚未签到

发表于 2018-10-29 12:03:21 | 显示全部楼层 |阅读模式
  1 基本概述
  Hadoop的命令位于${HADOOP_HOME}/bin、${HADOOP_HOME}/sbin、${HADOOP_HOME}/libexec下面。包含了Linux的shell脚本和windows的批处理文件。本文主要解析linux下的shell脚本。
  2 脚本详解
  2.1 start-all.sh
  要启动Hadoop的各节点和其他服务,这是一个绕不开的启动脚本,该脚本位于${HADOOP_HOME}/sbin下。不过在Hadoop的2.x版本中,Hadoop官方已经宣布被弃用了。接下来,就详细地分析一下该脚本是如何工作的:
  1、首先脚本开头有一段注释:# Start all hadoop daemons.  Run this on master node.中文意思是:启动所有的进程(也就是各节点),在管理节点(也就是namenode-名称节点)上运行该脚本。
  2、如果是2.x版本会有echo "This script is Deprecated. Instead usestart-dfs.sh and start-yarn.sh"的提示,意思该脚本已经过时,该脚本已经被start-dfs.sh和 start-yarn.sh替代使用。
  3、bin=`dirname"${BASH_SOURCE-$0}"`,提取start-all.sh的所在的绝对路径。
  4、bin=`cd"$bin"; pwd`,切换到start-all.sh的所在目录下,并将路径赋值给bin。
  5、DEFAULT_LIBEXEC_DIR="$bin"/../libexec,获取${HADOOP_HOME}/libexec的绝对路径以备后用。
  6、HADOOP_LIBEXEC_DIR=${HADOOP_LIBEXEC_DIR:-$DEFAULT_LIBEXEC_DIR},为HADOOP_LIBEXEC_DIR变量三元赋值。如果HADOOP_LIBEXEC_DIR为空或者环境变量没有配置,就赋值默认的绝对路径,为下一步执行该目录下面的脚本做准备。
  7、.$HADOOP_LIBEXEC_DIR/hadoop-config.sh。执行${HADOOP_HOME}/libexec/hadoop-config.sh脚本。为后面执行启动各节点和启动YARN做预处理。
  8、执行节点启动脚本
  if [ -f"${HADOOP_HDFS_HOME}"/sbin/start-dfs.sh ]; then
  "${HADOOP_HDFS_HOME}"/sbin/start-dfs.sh--config $HADOOP_CONF_DIR
  fi
  这段脚本的意图是:如果${HADOOP_HDFS_HOME}/sbin/start-dfs.sh为文件,则联合--config参数及其后面的参数值执行start-dfs.sh。start-dfs.sh后面做详细分析。
  另外看注释:# start hdfsdaemons if hdfs is present,中文意思是:启动hdfs进程
  9、执行YRAN调度服务
  if [ -f"${HADOOP_YARN_HOME}"/sbin/start-yarn.sh ]; then
  "${HADOOP_YARN_HOME}"/sbin/start-yarn.sh --config$HADOOP_CONF_DIR
  fi
  这段脚本的意图是:如果${HADOOP_HDFS_HOME}/sbin/start-yarn.sh为文件,则联合--config参数及其后面的参数值执行start-yarn.sh。start-yarn.sh后面做详细分析。
  另外看注释:# start yarndaemons if yarn is present,中文意思是:启动yarn进程
  备注:${HADOOP_HDFS_HOME}已经在hadoop-config.sh做了预处理。hadoop-config.sh后面做详细的分析。
  2.2 hadoop-config.sh
  该脚本位于${HADOOP_HOME}/libexec下。该脚本是在启动节点和其他服务之前必须要执行的一个脚本。它的主要目的使用启动Hadoop之前做一些环境变量预处理。接下来,就详细地分析一下该脚本是如何工作的:

  1、文件最前面的注释:Resolvelinks ($0 may be a softlink) and convert a>  2、执行hadoop-layout.sh脚本
  this="${BASH_SOURCE-$0}"
  common_bin=$(cd-P -- "$(dirname -- "$this")" && pwd -P)
  script="$(basename-- "$this")"
  this="$common_bin/$script"
  [ -f"$common_bin/hadoop-layout.sh" ] && ."$common_bin/hadoop-layout.sh"
  这段脚本的意图就是找出hadoop-layout.sh并执行,如果没有找出来就不执行。同时有些变量为后面的程序执行做准备。
  3、准备HDFS、YRAN、Mapreduce的jar包路径并设置路径
  HADOOP_COMMON_DIR=${HADOOP_COMMON_DIR:-"share/hadoop/common"}
  HADOOP_COMMON_LIB_JARS_DIR=${HADOOP_COMMON_LIB_JARS_DIR:-"share/hadoop/common/lib"}
  HADOOP_COMMON_LIB_NATIVE_DIR=${HADOOP_COMMON_LIB_NATIVE_DIR:-"lib/native"}
  HDFS_DIR=${HDFS_DIR:-"share/hadoop/hdfs"}
  HDFS_LIB_JARS_DIR=${HDFS_LIB_JARS_DIR:-"share/hadoop/hdfs/lib"}
  YARN_DIR=${YARN_DIR:-"share/hadoop/yarn"}
  YARN_LIB_JARS_DIR=${YARN_LIB_JARS_DIR:-"share/hadoop/yarn/lib"}
  MAPRED_DIR=${MAPRED_DIR:-"share/hadoop/mapreduce"}
  MAPRED_LIB_JARS_DIR=${MAPRED_LIB_JARS_DIR:-"share/hadoop/mapreduce/lib"}
  4、设置${Hadoop_Home}的根目录的环境变量
  HADOOP_DEFAULT_PREFIX=$(cd -P --"$common_bin"/.. && pwd -P)
  HADOOP_PREFIX=${HADOOP_PREFIX:-$HADOOP_DEFAULT_PREFIX}
  export HADOOP_PREFIX
  5、判断输出参数
  if [ $# -gt 1 ]
  then
  if ["--config" = "$1" ]
  then
  shift
  confdir=$1
  if [ ! -d "$confdir" ]; then
  echo "Error: Cannot find configuration directory: $confdir"
  exit 1
  fi
  shift
  HADOOP_CONF_DIR=$confdir
  fi
  fi
  这段代码参数的意思:$#是表示输入的参数个数,如果个数大于1,则判断—config后面的参数是否是一个目录。如果不是,则退出执行,如果是将传入的参数赋值给HADOOP_CONF_DIR变量,即将HADOOP_CONF_DIR变量定位到hadoop的配置目录。
  6、设置hadoop的日志级别
  if [ $# -gt 1 ]
  then
  if [ "--loglevel" = "$1"]
  then
  shift
  HADOOP_LOGLEVEL=$1
  shift
  fi
  fi
  HADOOP_LOGLEVEL="${HADOOP_LOGLEVEL:-INFO}"
  这段代码的意思是:如果没有传入日志参数,则默认为INFO级别。
  7、设置HADOOP_CONF_DIR配置的环境变量,也是启动Hadoop的工作目录(--config后面的参数值)
  if [ -e"${HADOOP_PREFIX}/conf/hadoop-env.sh" ]; then
  DEFAULT_CONF_DIR="conf"
  else
  DEFAULT_CONF_DIR="etc/hadoop"
  fi
  exportHADOOP_CONF_DIR="${HADOOP_CONF_DIR:-$HADOOP_PREFIX/$DEFAULT_CONF_DIR}"
  这段的代码的意图是:如果参数值存在,输出传入的参数值;如果不存在,使用默认的目录,一般位于${HADOOP_HOME}/etc/Hadoop.
  8、设置部署各个节点hostname配置的环境变量
  if [ $# -gt 1 ]
  then
  if [ "--hosts" = "$1" ]
  then
  shift
  exportHADOOP_SLAVES="${HADOOP_CONF_DIR}/$1"
  shift
  elif [ "--hostnames" ="$1" ]
  then
  shift
  export HADOOP_SLAVE_NAMES=$1
  shift
  fi
  fi
  这段代码:读取${HADOOP_HOME}/${HADOOP_CONF_DIR}/slaves文件里面的主机配置列表并输出HADOOP_SLAVES或者HADOOP_SLAVE_NAMES环境变量。
  9、设置hadoop运行的其他环境变量
  类似于上面:如果在操作系统的设置过环境变量,则直接使用。如果没有设置,则设置成默认的环境变量。这些环境变量有:JAVA_HOME、CLASSPATH、JVM启动参数、JAVA_LIBRARY_PATH、MALLOC_ARENA_MAX等,这里不再一一赘述。如果有不懂的地方,自行查询java的相关环境变量配置资料
  同时还设置了以下的环境变量:HADOOP_HOME、HADOOP_OPTS、HADOOP_COMMON_HOME、TOOL_PATH、HADOOP_HDFS_HOME、LD_LIBRARY_PATHHADOOP_YARN_HOME、HADOOP_MAPRED_HOME。这些环境变量的设置都引用了前面的变量,这里也不再一一赘述。
  2.3 start-hdfs.sh
  该脚本位于${HADOOP_HOME}/sbin下。该脚本是启动集群各节点(包括名称主节点、各个名称从节点、各个数据节点)的一个脚本。接下来,就详细地分析一下该脚本是如何工作的:
  1、文件最前面的注释:Starthadoop dfs daemons。中文意思是:启动dfs的各个进程。
  2、提示信息变量:usage="Usage:start-dfs.sh [-upgrade|-rollback] [other options such as -clusterId]"。提示在执行这个脚本的时候需要主要哪些东西的一个提示信息。
  3、执行预处理脚本,这个脚本在前面已经分析过了,不再赘述。
  bin=`dirname"${BASH_SOURCE-$0}"`
  bin=`cd "$bin"; pwd`
  DEFAULT_LIBEXEC_DIR="$bin"/../libexec
  HADOOP_LIBEXEC_DIR=${HADOOP_LIBEXEC_DIR:-$DEFAULT_LIBEXEC_DIR}
  . $HADOOP_LIBEXEC_DIR/hdfs-config.sh
  则也就是不推荐使用的start-all.sh这个脚本的原因所在。
  4、根据传入参数进行判断进行相应的变量设置
  if [[ $# -ge 1]]; then
  startOpt="$1"
  shift
  case "$startOpt" in
  -upgrade)
  nameStartOpt="$startOpt"
  ;;
  -rollback)
  dataStartOpt="$startOpt"
  ;;
  *)
  echo $usage
  exit 1
  ;;
  esac
  fi
  这段代码的意思是:如果参数值的个数大于等于1的时候,如果参数是upgrade,则设置nameStartOpt变量以备后用;如果是rollback,则设置dataStartOpt变量以备后用。
  5、添加名称节点可能参数值
  nameStartOpt="$nameStartOpt$@"
  6、启动管理(主)名称节点
  NAMENODES=$($HADOOP_PREFIX/bin/hdfsgetconf -namenodes)
  echo"Starting namenodes on [$NAMENODES]"
  "$HADOOP_PREFIX/sbin/hadoop-daemons.sh"\
  --config"$HADOOP_CONF_DIR" \
  --hostnames"$NAMENODES" \
  --script"$bin/hdfs" start namenode $nameStartOpt
  这段的意思是:将config、hostnames、script的参数值传给hadoop-daemons.sh执行,启动名称主节点。实际上是通过hdfs命令启动的。
  $($HADOOP_PREFIX/bin/hdfs getconf -namenodes)是在提取主名称节点的主机名。
  --script "$bin/hdfs" startnamenode $nameStartOpt实际启动名称节点。
  hadoop-daemons.sh脚本后面在做详细分析
  7、启动数据节点
  if [ -n"$HADOOP_SECURE_DN_USER" ]; then
  echo \
  "Attempting to start secure cluster,skipping datanodes. " \
  "Run start-secure-dns.sh as root tocomplete startup."
  else
  "$HADOOP_PREFIX/sbin/hadoop-daemons.sh"\
  --config "$HADOOP_CONF_DIR" \
  --script "$bin/hdfs" startdatanode $dataStartOpt
  fi
  这段的意思是:将config、script的参数值传给hadoop-daemons.sh执行,启动数据节点节点。实际上也是通过hdfs命令启动的。
  if [ -n "$HADOOP_SECURE_DN_USER"]; then这段代码可以忽略,基本不用。
  --script "$bin/hdfs" startdatanode $dataStartOpt实际启动名称节点。
  8、启动从名称节点
  SECONDARY_NAMENODES=$($HADOOP_PREFIX/bin/hdfsgetconf -secondarynamenodes 2>/dev/null)
  if [ -n"$SECONDARY_NAMENODES" ]; then
  echo "Starting secondary namenodes[$SECONDARY_NAMENODES]"
  "$HADOOP_PREFIX/sbin/hadoop-daemons.sh"\
  --config "$HADOOP_CONF_DIR" \
  --hostnames"$SECONDARY_NAMENODES" \
  --script "$bin/hdfs" startsecondarynamenode
  Fi
  这段的意思是:将config、hostnames、script的参数值传给hadoop-daemons.sh执行,启动名称主节点。实际上是通过hdfs命令启动的。
  SECONDARY_NAMENODES=$($HADOOP_PREFIX/bin/hdfsgetconf -secondarynamenodes 2>/dev/null),是在提取从名称节点的主机名。
  --script "$bin/hdfs" start namenode secondarynamenode实际启动名称节点。
  9、后面的执行
  后面的执行过程,后面有时间一一补充。
  2.4 hadoop-daemons.sh
  该脚本位于${HADOOP_HOME}/sbin下。该脚本是具体执行启动集群各节点(包括名称主节点、各个名称从节点、各个数据节点)的一个脚本。接下来,就详细地分析一下该脚本是如何工作的:
  1、其它的代码可以不做重点关注
  2、exec"$bin/slaves.sh" --config $HADOOP_CONF_DIR cd"$HADOOP_PREFIX" \; "$bin/hadoop-daemon.sh" --config$HADOOP_CONF_DIR "$@"
  拆解这段代码:
  A、先执行slaves.sh脚本,这个脚本是根据slaves的主机列表迭代执行hadoop-daemon.sh脚本。
  B、然后将所有参数传入并执行hadoop-daemon.sh脚本。
  2.5 hadoop-daemon.sh
  该脚本位于${HADOOP_HOME}/sbin下。该脚本是具体执行启动集群各节点(包括名称主节点、各个名称从节点、各个数据节点)的一个脚本。接下来,就详细地分析一下该脚本是如何工作的:
  1、先调用hadoop-config.sh脚本,不再赘述。
  2、提取hadoop命令并设置变量:
  hadoopScript="$HADOOP_PREFIX"/bin/Hadoop
  3、提取命令(或是启动命令,或是停止命令),提取节点(或者名称节点,或是数据节点)
  hadoopScript="$HADOOP_PREFIX"/bin/hadoop
  if[ "--script" = "$1" ]
  then
  shift
  hadoopScript=$1
  shift
  fi
  startStop=$1
  shift
  command=$1
  shift
  4、输出日志相关
  hadoop_rotate_log()
  {
  log=$1;
  num=5;
  if [ -n "$2" ]; then
  num=$2
  fi
  if [ -f "$log" ]; then # rotatelogs
  while [ $num -gt 1 ]; do
  prev=`expr $num - 1`
  [ -f "$log.$prev" ] && mv "$log.$prev""$log.$num"
  num=$prev
  done
  mv "$log" "$log.$num";
  fi
  }
  5、执行环境变量设置脚本
  if[ -f "${HADOOP_CONF_DIR}/hadoop-env.sh" ]; then
  ."${HADOOP_CONF_DIR}/hadoop-env.sh"
  fi
  6、根据启动节点的不同重新设置不同的变量值
  #Determine if we're starting a secure datanode, and if so, redefine appropriatevariables
  if[ "$command" == "datanode" ] && [ "$EUID"-eq 0 ] && [ -n "$HADOOP_SECURE_DN_USER" ]; then
  exportHADOOP_PID_DIR=$HADOOP_SECURE_DN_PID_DIR
  exportHADOOP_LOG_DIR=$HADOOP_SECURE_DN_LOG_DIR
  exportHADOOP_IDENT_STRING=$HADOOP_SECURE_DN_USER
  starting_secure_dn="true"
  fi
  #Determineif we're starting a privileged NFS, if so, redefine the appropriate variables
  if[ "$command" == "nfs3" ] && [ "$EUID" -eq0 ] && [ -n "$HADOOP_PRIVILEGED_NFS_USER" ]; then
  exportHADOOP_PID_DIR=$HADOOP_PRIVILEGED_NFS_PID_DIR
  exportHADOOP_LOG_DIR=$HADOOP_PRIVILEGED_NFS_LOG_DIR
  exportHADOOP_IDENT_STRING=$HADOOP_PRIVILEGED_NFS_USER
  starting_privileged_nfs="true"
  fi
  7、中间的都是输出日志和设置其他临时变量和环境变量,不做重点介绍,请自行参考脚本
  8、启动或者停止节点
  case$startStop in
  (start)
  [ -w "$HADOOP_PID_DIR" ] ||  mkdir -p "$HADOOP_PID_DIR"
  if [ -f $pid ]; then
  if kill -0 `cat $pid` > /dev/null2>&1; then
  echo $command running as process `cat$pid`.  Stop it first.
  exit 1
  fi
  fi
  if [ "$HADOOP_MASTER" !="" ]; then
  echo rsync from $HADOOP_MASTER
  rsync -a -e ssh --delete --exclude=.svn--exclude='logs/*' --exclude='contrib/hod/logs/*' $HADOOP_MASTER/"$HADOOP_PREFIX"
  fi
  hadoop_rotate_log $log
  echo starting $command, logging to $log
  cd "$HADOOP_PREFIX"
  case $command in
  namenode|secondarynamenode|datanode|journalnode|dfs|dfsadmin|fsck|balancer|zkfc)
  if [ -z "$HADOOP_HDFS_HOME"]; then
  hdfsScript="$HADOOP_PREFIX"/bin/hdfs
  else
  hdfsScript="$HADOOP_HDFS_HOME"/bin/hdfs
  fi
  nohup nice -n $HADOOP_NICENESS$hdfsScript --config $HADOOP_CONF_DIR $command "$@" >"$log" 2>&1 < /dev/null &
  ;;
  (*)
  nohup nice -n $HADOOP_NICENESS$hadoopScript --config $HADOOP_CONF_DIR $command "$@" >"$log" 2>&1 < /dev/null &
  ;;
  esac
  echo $! > $pid
  sleep 1
  head "$log"
  # capture the ulimit output
  if [ "true" ="$starting_secure_dn" ]; then
  echo "ulimit -a for secure datanodeuser $HADOOP_SECURE_DN_USER" >> $log
  # capture the ulimit info for theappropriate user
  su --shell=/bin/bash$HADOOP_SECURE_DN_USER -c 'ulimit -a' >> $log 2>&1
  elif [ "true" ="$starting_privileged_nfs" ]; then
  echo "ulimit -a for privileged nfsuser $HADOOP_PRIVILEGED_NFS_USER" >> $log
  su --shell=/bin/bash $HADOOP_PRIVILEGED_NFS_USER-c 'ulimit -a' >> $log 2>&1
  else
  echo "ulimit -a for user $USER">> $log
  ulimit -a >> $log 2>&1
  fi
  sleep 3;
  if ! ps -p $! > /dev/null ; then
  exit 1
  fi
  ;;
  (stop)
  if [ -f $pid ]; then
  TARGET_PID=`cat $pid`
  if kill -0 $TARGET_PID > /dev/null2>&1; then
  echo stopping $command
  kill $TARGET_PID
  sleep $HADOOP_STOP_TIMEOUT
  if kill -0 $TARGET_PID > /dev/null2>&1; then
  echo "$command did not stopgracefully after $HADOOP_STOP_TIMEOUT seconds: killing with kill -9"
  kill -9 $TARGET_PID
  fi
  else
  echo no $command to stop
  fi
  rm -f $pid
  else
  echo no $command to stop
  fi
  ;;
  (*)
  echo$usage
  exit 1
  ;;
  esac
  这是一个分支执行流程,分为启动节点和停止节点:
  A、启动节点分支:在该分支下,首先判断节点主机上的PID(其实就是默认设置的端口)是否被占用,如果被占用则停止启动。如果没有被占用,则开始打印日志,也是我们在控制台上看到的日志(echo starting $command, logging to $log)。表明开始启动节点上的hadoop进程,然后根据$command变量判断启动哪个节点,最后将所有的参数传入hdfs命令启动节点,至此,该节点就启动起来了。
  B、停止节点分支:在该分支下,首先判断节点主机上的PID(其实就是默认设置的端口)是否被占用,如果被占用则杀掉进程,如果没有被杀掉,则使用kill-9强制杀掉。如果PID没有被占用,则会打印提示信息:“没有XX节点需要停止”, 至此,该节点就停止服务了。
  2.6 hdfs
  该脚本首先判断是否有参数传入或者参数是否正确,如果没有参数或者参数错误,就会提示用户需要传递参数或者传递正确的参数。
  然后根据参数值判断后调用jdk(JAVA_HOME)下相应的脚本,最后启动相应的java进程。
  总而言之,这个脚本才是启动hadoop的最终归宿,如果能掌握hadoop里面的所有入口函数,也可以认为这个脚本也不是最终归宿,因为这个脚本的最终目的就是通过调用jdk下面的java命令启动Hadoop的必要入口函数,也就是main方法,最终达到启动整个Hadoop集群的目的。
  2.7 start-yarn.sh
  该脚本的执行流程与start-hdfs的执行流程类似,请自行参考该shell脚本,这里不再赘述。
  2.8 yarn-daemons.sh
  该脚本的执行流程与hadoop-daemons.sh的执行流程类似,请自行参考该shell脚本,这里不再赘述。
  2.9 yarn-daemon.sh
  该脚本的执行流程与hadoop-daemon.sh的执行流程类似,请自行参考该shell脚本,这里不再赘述。
  2.10 各停止脚本
  从上面hadoop-daemon.sh可以看出,停止各节点的服务,无外乎也就是先提取相应的环境变量,然后杀掉相应的进程,将占用端口释放出来,没什么大书特书的。如有兴趣,可以自行研究停止脚本,这里不再做详细分析。


运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-627984-1-1.html 上篇帖子: Hadoop Hive 下篇帖子: Hadoop序列化与压缩
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表