【问题标题】:Cannot start cluster from namenode (master): different $HADOOP_HOME on datanode (slave) and namenode (master)无法从 namenode (master) 启动集群:datanode (slave) 和 namenode (master) 上的 $HADOOP_HOME 不同
【发布时间】:2015-01-11 01:05:26
【问题描述】:

我在 master 和 slave 上使用 Hadoop 1.2.1,但我将它们安装在不同的目录中。因此,当我在 master 上调用 bin/start-dfs.sh 时,会出现以下错误。

partho@partho-Satellite-L650: starting datanode, logging to /home/partho/hadoop/apache/hadoop-1.2.1/libexec/../logs/hadoop-partho-datanode-partho-Satellite-L650.out
hduser@node2-VirtualBox: bash: line 0: **cd: /home/partho/hadoop/apache/hadoop-1.2.1/libexec/..: No such file or directory**
hduser@node2-VirtualBox: bash: **/home/partho/hadoop/apache/hadoop-1.2.1/bin/hadoop-daemon.sh: No such file or directory**
partho@partho-Satellite-L650: starting secondarynamenode, logging to /home/partho/hadoop/apache/hadoop-1.2.1/libexec/../logs/hadoop-partho-secondarynamenode-partho-Satellite-L650.out

如下所示,在 Master 上创建的守护进程很好

partho@partho-Satellite-L650:~/hadoop/apache/hadoop-1.2.1$ jps
4850 Jps

4596 DataNode

4441 NameNode

4764 SecondaryNameNode

很明显,Hadoop 正在尝试使用主服务器上的$HADOOP_HOME 来查找从服务器上的hadoop-daemon.shlibexec

如何配置单个数据节点/从属节点,以便当我从主节点启动集群时,检查各个从节点的 Hadoop 主目录是否有 hadoop-daemon.sh

【问题讨论】:

    标签: hadoop hadoop2


    【解决方案1】:

    Hadoop 通常在名为 hadoop-env.sh 的文件中设置每个节点上的 HADOOP_HOME 环境变量。

    您可以使用相应节点的路径更新每个节点上的 hadoop-env.sh。它可能应该在 /home/partho/hadoop/apache/hadoop-1.2.1/ 中。可能希望先停止集群,以便它能够接收更改。

    如果你已经找到安装运行 找到 hadoop-env.sh 或查找 / -name "hadoop-env.sh"

    【讨论】:

      【解决方案2】:

      为了获得最佳解决方案,您应该将 hadoop 目录保留在您的任何目录中,但对于两者应该是相同的,例如示例:

      在主路径上:

      /opt/hadoop

      在从属路径上

      /opt/hadoop

      你使用哪个版本无关紧要,但目录名称应该相同

      【讨论】:

      • 版本应该很重要。 Hadoop3 属性不适用于 Hadoop 2 或 1
      • 如果你在master上有hadoop3,在slave上有hadoop2,为什么它不能正常工作,但是目录名应该是hadoop,它只会从master获取数据并在slave上搜索相同的配置文件。
      • 目录名称和位置并不重要。客户端与主服务器通信所使用的协议以及他们从文件中读取的属性很重要。
      • 例如,如果您有一个属性文件启用了 YARN Docker 容器并设置了 Erasure Coding HDFS 设置,那么它只适用于 Hadoop3,而不是更少
      • hadoop 3 支持api,2,1兼容
      【解决方案3】:

      一旦你设置了集群,从 master 启动所有守护进程

      bin/hadoop namenode -format(if required)
      bin/stop-dfs.sh
      bin/start-dfs.sh
      bin/start-mapred.sh
      

      为了从master启动所有节点,

      - you need to install ssh on each node
      - once you install ssh and generate ssh key in each server, try connecting each nodes from master
      - make sure slaves file in master node has all Ips of all nodes
      

      所以命令应该是

      - install ssh(in each node) : apt-get install openssh-server
      - once ssh is installed,generate key : ssh-keygen -t rsa -P ""
      - Create password less login from namenode to each node:
        ssh-copy-id -i $HOME/.ssh/id_rsa.pub user@datanodeIP
        user - hadoop user on each machine`enter code here`
      - put all nodes ip in slaves(in conf dir) file in namenode
      

      【讨论】:

        【解决方案4】:

        简答

        在主端

        hadoop-daemons.sh

        $HADOOP_HOME/sbin/hadoop-daemons.sh(不是$HADOOP_HOME/sbin/hadoop-daemon.sh,文件名中有s)中,有一行调用$HADOOP_HOME/sbin/slaves.sh。在我的版本(Hadoop v2.7.7)中,它显示:

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

        将其更改为以下行以使其尊重从端环境变量:

        exec "$bin/slaves.sh" "source" ".bash_aliases" \; "hadoop-daemon.sh" "$@"

        yarn-daemons.sh

        同样,在$HADOOP_HOME/sbin/yarn-daemons.sh 中,换行:

        exec "$bin/slaves.sh" --config $YARN_CONF_DIR cd "$HADOOP_YARN_HOME" \; "$bin/yarn-daemon.sh" --config $YARN_CONF_DIR "$@"

        exec "$bin/slaves.sh" "source" ".bash_aliases" \; "yarn-daemon.sh" "$@"

        在从属端

        将所有与Hadoop相关的环境变量放入$HOME/.bash_aliases

        开始/停止

        要启动 HDFS,只需在主端运行 start-dfs.sh。从端数据节点将启动,就好像hadoop-daemon.sh start datanode 从从端的交互式 shell 中执行一样。

        要停止 HDFS,只需运行 stop-dfs.sh


        注意

        以上更改已经完成。但是对于完美主义者,您可能还想修复sbin/hadoop-daemons.sh 的调用者,以便在转储它们时命令正确。在这种情况下,请在 Hadoop 脚本中找到所有出现的 hadoop-daemons.sh,并将 --script "$bin"/hdfs 替换为 --script hdfs(并将所有 --script "$bin"/something 替换为 --script something)。在我的例子中,所有的出现都是hdfs,并且由于从属端会在与hdfs相关时重写命令路径,因此无论是否有此修复,该命令都可以正常工作。

        这是sbin/start-secure-dns.sh 中的修复示例。

        变化:

        "$HADOOP_PREFIX"/sbin/hadoop-daemons.sh --config $HADOOP_CONF_DIR --script "$bin"/hdfs start datanode $dataStartOpt

        "$HADOOP_PREFIX"/sbin/hadoop-daemons.sh --config $HADOOP_CONF_DIR --script hdfs start datanode $dataStartOpt

        在我的版本(Hadoop v2.7.7)中,需要修复以下文件:

        • sbin/start-secure-dns.sh(出现 1 次)
        • sbin/stop-secure-dns.sh(出现 1 次)
        • sbin/start-dfs.sh(出现 5 次)
        • sbin/stop-dfs.sh(出现 5 次)

        说明

        sbin/slaves.sh 中,通过ssh 连接主设备和从设备的线路为:

        ssh $HADOOP_SSH_OPTS $slave $"${@// /\\ }" \
           2>&1 | sed "s/^/$slave: /" &
        

        我在它之前添加了 3 行来转储变量:

         printf 'XXX HADOOP_SSH_OPTS: %s\n' "$HADOOP_SSH_OPTS"
         printf 'XXX slave: %s\n' "$slave"
         printf 'XXX command: %s\n' $"${@// /\\ }"
        

        sbin/hadoop-daemons.sh 中,调用sbin/slaves.sh 的行读取(我将其分成两行以防止滚动):

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

        sbin/start-dfs.sh 脚本调用sbin/hadoop-daemons.sh。这是执行sbin/start-dfs.sh 时的结果:

        Starting namenodes on [master]
        XXX HADOOP_SSH_OPTS: 
        XXX slave: master
        XXX command: cd
        XXX command: /home/hduser/hadoop-2.7.7
        XXX command: ;
        XXX command: /home/hduser/hadoop-2.7.7/sbin/hadoop-daemon.sh
        XXX command: --config
        XXX command: /home/hduser/hadoop-2.7.7/etc/hadoop
        XXX command: --script
        XXX command: /home/hduser/hadoop-2.7.7/sbin/hdfs
        XXX command: start
        XXX command: namenode
        master: starting namenode, logging to /home/hduser/hadoop-2.7.7/logs/hadoop-hduser-namenode-akmacbook.out
        XXX HADOOP_SSH_OPTS: 
        XXX slave: slave1
        XXX command: cd
        XXX command: /home/hduser/hadoop-2.7.7
        XXX command: ;
        XXX command: /home/hduser/hadoop-2.7.7/sbin/hadoop-daemon.sh
        XXX command: --config
        XXX command: /home/hduser/hadoop-2.7.7/etc/hadoop
        XXX command: --script
        XXX command: /home/hduser/hadoop-2.7.7/sbin/hdfs
        XXX command: start
        XXX command: datanode
        slave1: bash: line 0: cd: /home/hduser/hadoop-2.7.7: Permission denied
        slave1: bash: /home/hduser/hadoop-2.7.7/sbin/hadoop-daemon.sh: Permission denied
        Starting secondary namenodes [master]
        XXX HADOOP_SSH_OPTS: 
        XXX slave: master
        XXX command: cd
        XXX command: /home/hduser/hadoop-2.7.7
        XXX command: ;
        XXX command: /home/hduser/hadoop-2.7.7/sbin/hadoop-daemon.sh
        XXX command: --config
        XXX command: /home/hduser/hadoop-2.7.7/etc/hadoop
        XXX command: --script
        XXX command: /home/hduser/hadoop-2.7.7/sbin/hdfs
        XXX command: start
        XXX command: secondarynamenode
        master: starting secondarynamenode, logging to /home/hduser/hadoop-2.7.7/logs/hadoop-hduser-secondarynamenode-akmacbook.out
        

        从上面的结果可以看出,脚本不尊重从端.bashrcetc/hadoop/hadoop-env.sh


        解决方案

        从上面的结果,我们知道变量$HADOOP_CONF_DIR是在master端解析的。如果在slave端解决,问题就解决了。但是,由于ssh(附带命令)创建的shell 是非交互式shell,所以.bashrc 脚本不会在从端加载。因此,以下命令不会打印任何内容:

        ssh slave1 'echo $HADOOP_HOME'
        

        我们可以强制它加载.bashrc:

        ssh slave1 'source .bashrc; echo $HADOOP_HOME'
        

        但是,.bashrc(Ubuntu 18.04 中的默认值)中的以下块保护非交互式 shell:

        # If not running interactively, don't do anything
        case $- in
            *i*) ;;
              *) return;;
        esac
        

        此时,您可以从.bashrc 中删除上述块以尝试实现目标,但我认为这不是一个好主意。我没试过,但我认为守卫在那里是有原因的。

        在我的平台 (Ubuntu 18.04) 上,当我以交互方式登录时(通过控制台或 ssh),.profile 加载 .bashrc.bashrc 加载 .bash_aliases。因此,我习惯于保持所有.profile.bashrc.bash_logout 不变,并将任何自定义放入.bash_aliases

        如果您的平台上的.bash_aliases 未加载,请将以下代码附加到.bashrc

        if [ -f ~/.bash_aliases ]; then
            . ~/.bash_aliases
        fi
        

        回到问题。因此我们可以加载.bash_aliases 而不是.bashrc。因此,下面的代码完成了这项工作,并打印了来自从站的$HADOOP_HOME

        ssh slave1 'source .bash_aliases; echo $HADOOP_HOME'
        

        通过将这种技术应用于sbin/hadoop-daemons.sh 脚本,结果就是上面提到的Short Answer

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2013-02-26
          • 2015-03-26
          • 1970-01-01
          • 1970-01-01
          • 2018-05-11
          • 1970-01-01
          • 2015-07-28
          • 1970-01-01
          相关资源
          最近更新 更多