首页 > 代码库 > 大数据时代之hadoop(二):hadoop脚本解析

大数据时代之hadoop(二):hadoop脚本解析

“兵马未动,粮草先行”,要想深入的了解hadoop,我觉得启动或停止hadoop的脚本是必须要先了解的。说到底,hadoop就是一个分布式存储和计算框架,但是这个分布式环境是如何启动,管理的呢,我就带着大家先从脚本入手吧。说实话,hadoop的启动脚本写的真好,里面考虑的地方非常周全(比如说路径中有空格,软连接等)。

 

1、hadoop脚本简单介绍

 

   hadoop的脚本分布在$HADOOP_HOME下面的bin目录下和conf文件夹下,主要介绍如下:

bin目录下
        hadoop                 hadoop底层核心脚本,所有分布式程序最终都是通过这个脚本启动的。
hadoop-config.sh       基本别的脚本都会内嵌调用这个脚本,这个脚本作用就是解析命令行可选参数(--config :hadoop conf文件夹路径 和--hosts)
hadoop-daemon.sh       启动或停止本机command参数所指定的分布式程序,通过调用hadoop脚本实现。
hadoop-daemons.sh      启动所有机器上的hadoop分布式程序,通过调用slaves.sh实现。
slaves.sh              在所有的机器上运行一组指定的命令(通过ssh无密码登陆),供上层使用。
start-dfs.sh           在本机启动namenode,在slaves机器上启动datanode,在master机器上启动secondarynamenode,通过调用hadoop-daemon.sh和hadoop-daemons.sh实现。
start-mapred.sh        在本机启动jobtracker,在slaves机器上启动tasktracker,通过调用hadoop-daemon.sh和hadoop-daemons.sh实现。
start-all.sh           启动所有分布式hadoop程序,通过调用start-dfs.sh和start-mapred.sh实现。
start-balancer.sh      启动hadoop分布式环境复杂均衡调度程序,平衡各节点存储和处理能力。
还有几个stop 脚本,就不用详细说了。


conf目录下
hadoop-env.sh          配置hadoop运行时所需要的一些参数变量,比如JAVA_HOME,HADOOP_LOG_DIR,HADOOP_PID_DIR等。

 

2、脚本的魅力(详细解释)

hadoop的脚本写的真好,不服不行,从中学习到了好多知识。
 

2.1、hadoop-config.sh

 这个脚本比较简单,而且基本其他脚本都内嵌通过“. $bin/hadoop-config.sh”的形式调用此脚本,所以这个脚本就不用在第一行声明解释权,因为这种调用方式类似于把此脚本内容复制到父脚本里在同一个解释器里面运行。

     这个脚本主要做三部分内容:
 
1、软连接解析和绝对路径解析
[html] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. #软连接解析  
  2. this="$0"  
  3. while [ -h "$this" ]; do  
  4.   ls=`ls -ld "$this"`  
  5.   link=`expr "$ls" : ‘.*-> \(.*\)$‘`  
  6.   if expr "$link" : ‘.*/.*‘ > /dev/null; then  
  7.     this="$link"  
  8.   else  
  9.     this=`dirname "$this"`/"$link"  
  10.   fi  
  11. done  
  12.   
  13. #绝对路径解析  
  14. # convert relative path to absolute path  
  15. bin=`dirname "$this"`  
  16. script=`basename "$this"`  
  17. bin=`cd "$bin"; pwd`  
  18. this="$bin/$script"  
  19.   
  20. # the root of the Hadoop installation  
  21. export HADOOP_HOME=`dirname "$this"`/..  

2、命令行可选参数--config解析并赋值
[html] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. #check to see if the conf dir is given as an optional argument  
  2. if [ $# -gt 1 ]  
  3. then  
  4.     if [ "--config" = "$1" ]  
  5.       then  
  6.           shift  
  7.           confdir=$1  
  8.           shift  
  9.           HADOOP_CONF_DIR=$confdir  
  10.     fi  
  11. fi  

3、命令行可选参数--config解析并赋值
[html] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. #check to see it is specified whether to use the slaves or the  
  2. # masters file  
  3. if [ $# -gt 1 ]  
  4. then  
  5.     if [ "--hosts" = "$1" ]  
  6.     then  
  7.         shift  
  8.         slavesfile=$1  
  9.         shift  
  10.         export HADOOP_SLAVES="${HADOOP_CONF_DIR}/$slavesfile"  
  11.     fi  
  12. fi  
 

2.2、hadoop

 
    此脚本是hadoop脚本的核心,变量的设置,程序的启动都是通过这个脚本做的。
 
1、声明使用方法
[html] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. # if no args specified, show usage  
  2. if [ $# = 0 ]; then  
  3.   echo "Usage: hadoop [--config confdir] COMMAND"  
  4.   echo "where COMMAND is one of:"  
  5.   echo "  namenode -format     format the DFS filesystem"  
  6.   echo "  secondarynamenode    run the DFS secondary namenode"  
  7.   echo "  namenode             run the DFS namenode"  
  8.   echo "  datanode             run a DFS datanode"  
  9.   echo "  dfsadmin             run a DFS admin client"  
  10.   echo "  mradmin              run a Map-Reduce admin client"  
  11.   echo "  fsck                 run a DFS filesystem checking utility"  
  12.   echo "  fs                   run a generic filesystem user client"  
  13.   echo "  balancer             run a cluster balancing utility"  
  14.   echo "  jobtracker           run the MapReduce job Tracker node"   
  15.   echo "  pipes                run a Pipes job"  
  16.   echo "  tasktracker          run a MapReduce task Tracker node"   
  17.   echo "  job                  manipulate MapReduce jobs"  
  18.   echo "  queue                get information regarding JobQueues"   
  19.   echo "  version              print the version"  
  20.   echo "  jar <jar>            run a jar file"  
  21.   echo "  distcp <srcurl<desturl> copy file or directories recursively"  
  22.   echo "  archive -archiveName NAME <src>* <dest> create a hadoop archive"  
  23.   echo "  daemonlog            get/set the log level for each daemon"  
  24.   echo " or"  
  25.   echo "  CLASSNAME            run the class named CLASSNAME"  
  26.   echo "Most commands print help when invoked w/o parameters."  
  27.   exit 1  
  28. fi  

2、设置java运行环境

        代码简单,就不写出来了,包括JAVA_HOME,JAVA_HEAP_MAX,CLASSPATH,HADOOP_LOG_DIR,HADOOP_POLICYFILE。其中用到了设置IFS-储界定符号的环境变量,默认值是空白字符(换行,制表符或者空格)。

 

3、根据cmd设置运行时class

 

[html] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. # figure out which class to run  
  2. if [ "$COMMAND" = "namenode" ] ; then  
  3.   CLASS=‘org.apache.hadoop.hdfs.server.namenode.NameNode‘  
  4.   HADOOP_OPTS="$HADOOP_OPTS $HADOOP_NAMENODE_OPTS"  
  5. elif [ "$COMMAND" = "secondarynamenode" ] ; then  
  6.   CLASS=‘org.apache.hadoop.hdfs.server.namenode.SecondaryNameNode‘  
  7.   HADOOP_OPTS="$HADOOP_OPTS $HADOOP_SECONDARYNAMENODE_OPTS"  
  8. elif [ "$COMMAND" = "datanode" ] ; then  
  9.   CLASS=‘org.apache.hadoop.hdfs.server.datanode.DataNode‘  
  10.   HADOOP_OPTS="$HADOOP_OPTS $HADOOP_DATANODE_OPTS"  
  11. elif [ "$COMMAND" = "fs" ] ; then  
  12.   CLASS=org.apache.hadoop.fs.FsShell  
  13.   HADOOP_OPTS="$HADOOP_OPTS $HADOOP_CLIENT_OPTS"  
  14. elif [ "$COMMAND" = "dfs" ] ; then  
  15.   CLASS=org.apache.hadoop.fs.FsShell  
  16.   HADOOP_OPTS="$HADOOP_OPTS $HADOOP_CLIENT_OPTS"  
  17. elif [ "$COMMAND" = "dfsadmin" ] ; then  
  18.   CLASS=org.apache.hadoop.hdfs.tools.DFSAdmin  
  19.   HADOOP_OPTS="$HADOOP_OPTS $HADOOP_CLIENT_OPTS"  
  20. elif [ "$COMMAND" = "mradmin" ] ; then  
  21.   CLASS=org.apache.hadoop.mapred.tools.MRAdmin  
  22.   HADOOP_OPTS="$HADOOP_OPTS $HADOOP_CLIENT_OPTS"  
  23. elif [ "$COMMAND" = "fsck" ] ; then  
  24.   CLASS=org.apache.hadoop.hdfs.tools.DFSck  
  25.   HADOOP_OPTS="$HADOOP_OPTS $HADOOP_CLIENT_OPTS"  
  26. elif [ "$COMMAND" = "balancer" ] ; then  
  27.   CLASS=org.apache.hadoop.hdfs.server.balancer.Balancer  
  28.   HADOOP_OPTS="$HADOOP_OPTS $HADOOP_BALANCER_OPTS"  
  29. elif [ "$COMMAND" = "jobtracker" ] ; then  
  30.   CLASS=org.apache.hadoop.mapred.JobTracker  
  31.   HADOOP_OPTS="$HADOOP_OPTS $HADOOP_JOBTRACKER_OPTS"  
  32. elif [ "$COMMAND" = "tasktracker" ] ; then  
  33.   CLASS=org.apache.hadoop.mapred.TaskTracker  
  34.   HADOOP_OPTS="$HADOOP_OPTS $HADOOP_TASKTRACKER_OPTS"  
  35. elif [ "$COMMAND" = "job" ] ; then  
  36.   CLASS=org.apache.hadoop.mapred.JobClient  
  37. elif [ "$COMMAND" = "queue" ] ; then  
  38.   CLASS=org.apache.hadoop.mapred.JobQueueClient  
  39. elif [ "$COMMAND" = "pipes" ] ; then  
  40.   CLASS=org.apache.hadoop.mapred.pipes.Submitter  
  41.   HADOOP_OPTS="$HADOOP_OPTS $HADOOP_CLIENT_OPTS"  
  42. elif [ "$COMMAND" = "version" ] ; then  
  43.   CLASS=org.apache.hadoop.util.VersionInfo  
  44.   HADOOP_OPTS="$HADOOP_OPTS $HADOOP_CLIENT_OPTS"  
  45. elif [ "$COMMAND" = "jar" ] ; then  
  46.   CLASS=org.apache.hadoop.util.RunJar  
  47. elif [ "$COMMAND" = "distcp" ] ; then  
  48.   CLASS=org.apache.hadoop.tools.DistCp  
  49.   CLASSPATH=${CLASSPATH}:${TOOL_PATH}  
  50.   HADOOP_OPTS="$HADOOP_OPTS $HADOOP_CLIENT_OPTS"  
  51. elif [ "$COMMAND" = "daemonlog" ] ; then  
  52.   CLASS=org.apache.hadoop.log.LogLevel  
  53.   HADOOP_OPTS="$HADOOP_OPTS $HADOOP_CLIENT_OPTS"  
  54. elif [ "$COMMAND" = "archive" ] ; then  
  55.   CLASS=org.apache.hadoop.tools.HadoopArchives  
  56.   CLASSPATH=${CLASSPATH}:${TOOL_PATH}  
  57.   HADOOP_OPTS="$HADOOP_OPTS $HADOOP_CLIENT_OPTS"  
  58. elif [ "$COMMAND" = "sampler" ] ; then  
  59.   CLASS=org.apache.hadoop.mapred.lib.InputSampler  
  60.   HADOOP_OPTS="$HADOOP_OPTS $HADOOP_CLIENT_OPTS"  
  61. else  
  62.   CLASS=$COMMAND  
  63. fi  


4、设置本地库

 

[html] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. # setup ‘java.library.path‘ for native-hadoop code if necessary  
  2. JAVA_LIBRARY_PATH=‘‘  
  3. if [ -d "${HADOOP_HOME}/build/native" -o -d "${HADOOP_HOME}/lib/native" ]; then  
  4. #通过运行一个java 类来决定当前平台,挺有意思  
  5.   JAVA_PLATFORM=`CLASSPATH=${CLASSPATH} ${JAVA} -Xmx32m org.apache.hadoop.util.PlatformName | sed -e "s/ /_/g"`  
  6.     
  7.   if [ -d "$HADOOP_HOME/build/native" ]; then  
  8.     JAVA_LIBRARY_PATH=${HADOOP_HOME}/build/native/${JAVA_PLATFORM}/lib  
  9.   fi  
  10.     
  11.   if [ -d "${HADOOP_HOME}/lib/native" ]; then  
  12.     if [ "x$JAVA_LIBRARY_PATH" != "x" ]; then  
  13.       JAVA_LIBRARY_PATH=${JAVA_LIBRARY_PATH}:${HADOOP_HOME}/lib/native/${JAVA_PLATFORM}  
  14.     else  
  15.       JAVA_LIBRARY_PATH=${HADOOP_HOME}/lib/native/${JAVA_PLATFORM}  
  16.     fi  
  17.   fi  
  18. fi  


5、运行分布式程序

 

[html] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. # run it  
  2. xec "$JAVA" $JAVA_HEAP_MAX $HADOOP_OPTS -classpath "$CLASSPATH" $CLASS "$@"  



2.3、hadoop-daemon.sh       

       启动或停止本机command参数所指定的分布式程序,通过调用hadoop脚本实现,其实也挺简单的。

1、声明使用方法

 

[html] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. usage="Usage: hadoop-daemon.sh [--config <conf-dir>] [--hosts hostlistfile] (start|stop) <hadoop-command> <args...>"  
  2.   
  3. # if no args specified, show usage  
  4. if [ $# -le 1 ]; then  
  5.   echo $usage  
  6.   exit 1  
  7. fi  


2、设置环境变量


   
首先内嵌运行hadoop-env.sh脚本,然后设置HADOOP_PID_DIR等环境变量。


3、启动或停止程序

 

[html] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. case $startStop in  
  2.   
  3.   (start)  
  4.   
  5.     mkdir -p "$HADOOP_PID_DIR"  
  6.   
  7.     if [ -f $pid ]; then  
  8.     #如果程序已经启动的话,就停止,并退出。  
  9.       if kill -0 `cat $pid` > /dev/null 2>&1; then  
  10.         echo $command running as process `cat $pid`.  Stop it first.  
  11.         exit 1  
  12.       fi  
  13.     fi  
  14.   
  15.     if [ "$HADOOP_MASTER" != "" ]; then  
  16.       echo rsync from $HADOOP_MASTER  
  17.       rsync -a -e ssh --delete --exclude=.svn --exclude=‘logs/*‘ --exclude=‘contrib/hod/logs/*‘ $HADOOP_MASTER/ "$HADOOP_HOME"  
  18.     fi  
  19. # rotate 当前已经存在的log  
  20.     hadoop_rotate_log $log  
  21.     echo starting $command, logging to $log  
  22.     cd "$HADOOP_HOME"  
  23.     #通过nohup 和bin/hadoop脚本启动相关程序  
  24.     nohup nice -n $HADOOP_NICENESS "$HADOOP_HOME"/bin/hadoop --config $HADOOP_CONF_DIR $command "$@" > "$log" 2>&1 < /dev/null &  
  25.     #获取新启动的进程pid并写入到pid文件中  
  26.     echo $! > $pid  
  27.     sleep 1; head "$log"  
  28.     ;;  
  29.             
  30.   (stop)  
  31.   
  32.     if [ -f $pid ]; then  
  33.       if kill -0 `cat $pid` > /dev/null 2>&1; then  
  34.         echo stopping $command  
  35.         kill `cat $pid`  
  36.       else  
  37.         echo no $command to stop  
  38.       fi  
  39.     else  
  40.       echo no $command to stop  
  41.     fi  
  42.     ;;  
  43.   
  44.   (*)  
  45.     echo $usage  
  46.     exit 1  
  47.     ;;  
  48. esac  



2.4、slaves.sh


     
在所有的机器上运行一组指定的命令(通过ssh无密码登陆),供上层使用。


1、声明使用方法

 

[html] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. usage="Usage: slaves.sh [--config confdir] command..."  
  2.   
  3. # if no args specified, show usage  
  4. if [ $# -le 0 ]; then  
  5.   echo $usage  
  6.   exit 1  
  7. fi  


2、设置远程主机列表

 

[html] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. # If the slaves file is specified in the command line,  
  2. # then it takes precedence over the definition in   
  3. # hadoop-env.sh. Save it here.  
  4. HOSTLIST=$HADOOP_SLAVES  
  5.   
  6. if [ -f "${HADOOP_CONF_DIR}/hadoop-env.sh" ]; then  
  7.   . "${HADOOP_CONF_DIR}/hadoop-env.sh"  
  8. fi  
  9.   
  10. if [ "$HOSTLIST" = "" ]; then  
  11.   if [ "$HADOOP_SLAVES" = "" ]; then  
  12.     export HOSTLIST="${HADOOP_CONF_DIR}/slaves"  
  13.   else  
  14.     export HOSTLIST="${HADOOP_SLAVES}"  
  15.   fi  
  16. fi  


3、分别在远程主机执行相关命令

 

[html] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. #挺重要,里面技术含量也挺高,对远程主机文件进行去除特殊字符和删除空行;对命令行进行空格替换,并通过ssh在目标主机执行命令;最后等待命令在所有目标主机执行完后,退出。  
  2. for slave in `cat "$HOSTLIST"|sed  "s/#.*$//;/^$/d"`; do  
  3.  ssh $HADOOP_SSH_OPTS $slave $"${@// /\\ }" \  
  4.    2>&1 | sed "s/^/$slave: /" &  
  5.  if [ "$HADOOP_SLAVE_SLEEP" != "" ]; then  
  6.    sleep $HADOOP_SLAVE_SLEEP  
  7.  fi  
  8. done  
  9.   
  10. wait  


2.5、hadoop-daemons.sh

      启动远程机器上的hadoop分布式程序,通过调用slaves.sh实现。

1、声明使用方法
 
[html] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. # Run a Hadoop command on all slave hosts.  
  2.   
  3. usage="Usage: hadoop-daemons.sh [--config confdir] [--hosts hostlistfile] [start|stop] command args..."  
  4.   
  5. # if no args specified, show usage  
  6. if [ $# -le 1 ]; then  
  7.   echo $usage  
  8.   exit 1  
  9. fi  

2、在远程主机调用命令
[html] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. #通过salves.sh来实现  
  2. exec "$bin/slaves.sh" --config $HADOOP_CONF_DIR cd "$HADOOP_HOME" \; "$bin/hadoop-daemon.sh" --config $HADOOP_CONF_DIR "$@"  

2.6、start-dfs.sh 

      本机(调用此脚本的主机)启动namenode,在slaves机器上启动datanode,在master机器上启动secondarynamenode,通过调用hadoop-daemon.sh和hadoop-daemons.sh实现。


1、声明使用方式

 

[html] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. # Start hadoop dfs daemons.  
  2. # Optinally upgrade or rollback dfs state.  
  3. # Run this on master node.  
  4.   
  5. usage="Usage: start-dfs.sh [-upgrade|-rollback]"  


2、启动程序

 

[html] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. # start dfs daemons  
  2. # start namenode after datanodes, to minimize time namenode is up w/o data  
  3. # note: datanodes will log connection errors until namenode starts  
  4. #在本机(调用此脚本的主机)启动namenode  
  5. "$bin"/hadoop-daemon.sh --config $HADOOP_CONF_DIR start namenode $nameStartOpt  
  6. #在slaves机器上启动datanode  
  7. "$bin"/hadoop-daemons.sh --config $HADOOP_CONF_DIR start datanode $dataStartOpt  
  8. #在master机器上启动secondarynamenode  
  9. "$bin"/hadoop-daemons.sh --config $HADOOP_CONF_DIR --hosts masters start secondarynamenode  


2.7、start-mapred.sh 

     在本机(调用此脚本的主机)启动jobtracker,在slaves机器上启动tasktracker,通过调用hadoop-daemon.sh和hadoop-daemons.sh实现。
[html] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1.  # start mapred daemons  
  2. # start jobtracker first to minimize connection errors at startup  
  3. #在本机(调用此脚本的主机)启动jobtracker  
  4. "$bin"/hadoop-daemon.sh --config $HADOOP_CONF_DIR start jobtracker  
  5. #在master机器上启动tasktracker  
  6. "$bin"/hadoop-daemons.sh --config $HADOOP_CONF_DIR start tasktracker  


其他的脚本就都已经非常简单了,不用再详细说明了,只要看下,大致都能看懂。

 

对了,最后再说下hadoop的脚本里面用的shell解释器的声明吧。

 

[html] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. #!/usr/bin/env bash  

作用就是适应各种linux操作系统,能够找到 bash shell来解释执行本脚本,也挺有用的。

大数据时代之hadoop(二):hadoop脚本解析