Hadoop相关启动脚本分析

来源:互联网 发布:淘宝关键词工具 编辑:程序博客网 时间:2024/06/05 15:57

Hadoop相关启动脚本分析 有助于troubleshoot,顺便学习shell。

刚开始配置Hadoop难免出错,学习一下启动的脚本对分析错误还是很有帮助的。而且可以顺便学习shell。

我自己对shell命令还算比较熟,shell脚本基本看得懂,不过没具体去深究。所以下面提到的一些shell要点高手莫笑。

Hadoop 0.20.203

Hadoop主要命令集散地hadoop-config.sh hadoop-daemon.shRuns a Hadoop command as a daemon.hadoop-daemons.shRun a Hadoop command on all slave hosts.jsvcapplication to launch java daemonrccThe Hadoop record compiler 不懂slaves.shRun a shell command on all slave hosts.start-all.shstart-all = start-dfs + start+mapred # Start all hadoop daemons. Run this on master node.start-balancer.sh start-dfs.sh start-jobhistoryserver.sh start-mapred.sh stop-all.sh stop-balancer.sh stop-dfs.sh stop-jobhistoryserver.sh stop-mapred.sh 


至于bash的参考资料,首选这里 : http://www.gnu.org/software/bash/manual/bashref.html

更多Hadoop相关信息见Hadoop 专题页面http://www.codesky.net/topicnews.aspx?tid=13

我们从最常用的命令开始

start-all.sh

  1. bin=`dirname "$0"`
  2. bin=`cd "$bin"; pwd`
  3. . "$bin"/Hadoop-config.sh
  4. # start dfs daemons
  5. "$bin"/start-dfs.sh --config $Hadoop_CONF_DIR
  6. # start mapred daemons
  7. "$bin"/start-mapred.sh --config $Hadoop_CONF_DIR

第一部分是取得bin目录,方便调用其他sh。因为你无法知道是从什么目录运行脚本的,所以无法使用相对路径。

注意Hadoop-config.sh 前面有一个点。

参看资料

  1. . (a period)
  2. . filename [arguments]
  3. Read and execute commands from the filename argument in the current shell context.

我们获得一个很好的信息,all = dfs + mapred

之前都把namenode和jobtracker放到一起,datanode和tasktracker放到一起。其实dfs和mapred这两部分还是现对比较独立的。最新的Hadoop就把这两部分分开了。

start-dfs.sh / start-mapred.sh

注意daemon一个后面有s,一个没。带s的是启动slaves的。刚开始没看清还蛋疼了许久。

  1. "$bin"/Hadoop-daemon.sh --config $HADOOP_CONF_DIR start namenode $nameStartOpt
  2. "$bin"/Hadoop-daemons.sh --config $HADOOP_CONF_DIR start datanode $dataStartOpt
  3. "$bin"/Hadoop-daemons.sh --config $HADOOP_CONF_DIR --hosts masters start secondarynamenode

这里能解开我之前的一个疑惑:master和slaves的怎样配置master和slaves文件。

对于master:master文件只用来启动secondarynamenode,slaves只用来启动slaves

对于slaves:bin下的脚本没用到这两个文件 但其他部分可能用到

Hadoop-daemon.sh

log rotate,看得出日志的流动方向么? 新 1->2->3->4->5 旧
  1. hadoop_rotate_log ()
  2. {
  3. log=$1;
  4. num=5;
  5. if [ -n "$2" ]; then
  6. num=$2
  7. fi
  8. if [ -f "$log" ]; then # rotate logs
  9. while [ $num -gt 1 ]; do
  10. prev=`expr $num - 1`
  11. [ -f "$log.$prev" ] && mv "$log.$prev" "$log.$num"
  12. num=$prev
  13. done
  14. mv "$log" "$log.$num";
  15. fi
  16. }
  1. # Determine if we're starting a secure datanode, and if so, redefine appropriate variables
  2. if [ "$command" == "datanode" ] && [ "$EUID" -eq 0 ] && [ -n "$Hadoop_SECURE_DN_USER" ]; then

至于$EUID是系统变量。在Hadoop还用到IFS变量。

  1. nohup nice -n $Hadoop_NICENESS "$HADOOP_HOME"/bin/hadoop --config $HADOOP_CONF_DIR $command "$@" > "$log" 2>&1 < /dev/null &
  2. echo $! > $pid
nohup 是个好东西,ssh登录上主机,如果连接断了,当前执行的命令也会挂掉(sighup),有兴趣自己再去google。

nice用来调优先级,没用过

最终还是通过Hadoop来执行程序。

Hadoop-daemons.sh

  1. exec "$bin/slaves.sh" --config $HADOOP_CONF_DIR cd "$HADOOP_HOME" ; "$bin/hadoop-daemon.sh" --config $HADOOP_CONF_DIR "$@"

cd "$Hadoop_HOME" ; 似乎没啥用。。。暂时没发现有关联pwd的配置

实际调用了slaves.sh,"$bin/Hadoop-daemon.sh" 也传了过去。

这里能解开我之前的一个疑惑:master怎么知道slaves的的Hadoop安装在哪。

"$bin/hadoop-daemon.sh" 这坑爹的路径是master的,也就是说,各个机器的hadoop目录要一致。hadoop-daemon.sh 里面可以rsync from $HADOOP_MASTER

slaves.sh

  1. if [ "$HOSTLIST" = "" ]; then
  2. if [ "$Hadoop_SLAVES" = "" ]; then
  3. export HOSTLIST="${Hadoop_CONF_DIR}/slaves"
  4. else
  5. export HOSTLIST="${Hadoop_SLAVES}"
  6. fi
  7. fi
  8. for slave in `cat "$HOSTLIST"|sed "s/#.*$//;/^$/d"`; do
  9. ssh $Hadoop_SSH_OPTS $slave $"${@// /\ }"
  10. 2>&1 | sed "s/^/$slave: /" &
  11. if [ "$Hadoop_SLAVE_SLEEP" != "" ]; then
  12. sleep $Hadoop_SLAVE_SLEEP
  13. fi
  14. done
一般我们都用slaves文件来配置slaves机器。
  1. sed "s/#.*$//;/^$/d"`;
根据正则表达式的经验,看来是去掉#注释行和空行。
  1. $"${@// /\ }"

$@ = $1 $2 ...

${@// /\ }为带有空格的参数加上空格转义。

$"..." 本土化?不知有啥意义,不都是英文么?

资料:

  1. ${parameter/pattern/string}
  2. The pattern is expanded to produce a pattern just as in filename expansion. Parameter is expanded and the longest match of
  3. pattern against its value is replaced with string. If pattern begins with ‘/’, all matches of pattern are replaced with string.
  4. Normally only the first match is replaced. If pattern begins with ‘#’, it must match at the beginning of the expanded value of
  5. parameter. If pattern begins with ‘%’, it must match at the end of the expanded value of parameter. If string is null, matches of
  6. pattern are deleted and the / following pattern may be omitted. If parameter is ‘@’ or ‘*’, the substitution operation is
  7. applied to each positional parameter in turn, and the expansion is the resultant list. If parameter is an array variable
  8. subscripted with ‘@’ or ‘*’, the substitution operation is applied to each member of the array in turn, and the expansion is
  9. the resultant list.
  10. Bash supports the $"..." quoting syntax to do locale-specific translation of the characters between the double quotes.

这里能解开我之前的一个疑惑:master怎么去启动slaves的。

原来是通过ssh命令

Hadoop-config.sh

  1. # resolve links - $0 may be a softlink
  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
取个绝对地址也搞得这么蛋疼。取出链接 -> 后面的部分。如果带有/就是绝对路径链接?不对吧??不然就是相对链接,需要拼装上当前目录。

果然是bug。https://issues.apache.org/jira/browse/HADOOP-7089 我用的是0.20.203版本。可以看看fix好的版本

  1. # Resolve links ($0 may be a softlink) and convert a relative path
  2. # to an absolute path. NB: The -P option requires bash built-ins
  3. # or POSIX:2001 compliant cd and pwd.
  4. this="${BASH_SOURCE-$0}"
  5. common_bin=$(cd -P -- "$(dirname -- "$this")" && pwd -P)
  6. script="$(basename -- "$this")"
  7. this="$common_bin/$script"
奇怪,在gnu的manual没到${BASH_SOURCE-$0} 这种 Shell Parameter Expansion,这里才有 http://pubs.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html#tag_02_06_02 坑爹啊

-- 的作用是表示参数接收已结束 http://pubs.opengroup.org/onlinepubs/009695399/utilities/xcu_chap01.html#tag_01_11

也就是说,比如

grep -- -v file
-v是内容,不是grep的参数了。


man pwd ,找到

-P, --physical
avoid all symlinks


Hadoop

  1. exec "$JAVA" -Dproc_$COMMAND $JAVA_HEAP_MAX $HADOOP_OPTS -classpath "$CLASSPATH" $CLASS "$@"

最终启动java class

相关阅读:

Hadoop datanode启动失败:Hadoop安装目录权限的问题 http://www.codesky.net/Linux/2011-12/49389.htm
在Eclipse下搭建Hadoop开发环境各种问题的解决 http://www.codesky.net/Linux/2012-02/54597.htm