zoukankan      html  css  js  c++  java
  • 解决关闭Hadoop时no namenode to stop异常

    问题描述

    部门的Hadoop集群运行有一个多月了,今天需要做点调整,但是突然发现Hadoop不能正常关闭!

    Hadoop版本:2.6.0

    具体情况如下:

    [root@master ~]# stop-dfs.sh 
    Stopping namenodes on [master]
    master: no namenode to stop
    slave2: no datanode to stop
    slave1: no datanode to stop
    ...

    问题原因

    执行jps,发现namenode,datanode等进程都正常运行着。纳了闷!

    谁报的错就找谁吧,于是就开始阅读hadoop-daemon.sh脚本文件,结果找出问题原因了。

    首先找到报错的位置,在文件的最后几行:

     if [ -f $pid ]; then
          TARGET_PID=`cat $pid`
          if kill -0 $TARGET_PID > /dev/null 2>&1; then
            echo stopping $command
            kill $TARGET_PID
            sleep $HADOOP_STOP_TIMEOUT
            if kill -0 $TARGET_PID > /dev/null 2>&1; then
              echo "$command did not stop gracefully 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

    代码很多,我们只看我们关心的部分:

    if [ -f $pid ]; then
         ....#省略n多行
        else
          echo no $command to stop
     fi

    这样就很明显了,如果pid文件不存在就会打印:no  xxx to  stop

    那么pid是什么文件,为什么会不存在,找到pid变量的声明语句,在脚本文件的第107行:

    pid=$HADOOP_PID_DIR/hadoop-$HADOOP_IDENT_STRING-$command.pid #第107行

    接着再找HADOOP_PID_DIR变量的声明部分:

    首先在脚本注释部分找了很关键的一句话:

    #   HADOOP_PID_DIR   The pid files are stored. /tmp by default.

    我们知道了,HADOOP_PID_DIR  变量保存的是pid文件的存储路径。默认存储在/tmp目录中,代码如下:

    if [ "$HADOOP_PID_DIR" = "" ]; then   //97~99行
      HADOOP_PID_DIR=/tmp
    fi

    那么这个pid文件是啥呢。Hadoop启动后,会把进程的PID号存储在一个文件中,这样执行stop-dfs脚本时就可以按照进程PID去关闭进程了。

    现在问题原因很明确了,就是/tmp目录下的hadoop-*.pid的文件找不到了。

    解决问题

    那就看看/tmp目录下还有啥:

    [root@slave1 ~]# ll /tmp/
    srwxr-x--- 1 root root    0 Mar 26 13:39 Aegis-<Guid(5A2C30A2-A87D-490A-9281-6765EDAD7CBA)>
    drwxr-xr-x 2 root root 4096 Apr 10 13:55 hsperfdata_root
    srwxr-x--- 1 root root    0 Mar 26 13:39 qtsingleapp-aegisG-46d2-0
    srwxrwxrwx 1 root root    0 Mar 26 13:39 qtsingleapp-aegiss-a5d2-0

    额,除了我们需要的,其他啥都有!

    我们知道/tmp是临时目录,系统会定时清理该目录中的文件。显然把pid文件放在这里是不靠谱的,pid文件长时间不被访问,早被清理了!

    既然Hadoop不知道需要关闭哪些进程了,那我们只能手动关闭了!

    先用ps -ef查看namenodedatanode等进程的PID,然后用kill -9干掉即可!

    重启Hadoop后再看看/tmp目录的变化,多出了下面几个文件:

    [root@master ~]# ll /tmp
    -rw-r--r-- 1 root root    6 Apr 10 13:39 hadoop-root-namenode.pid
    -rw-r--r-- 1 root root    6 Apr 10 13:39 hadoop-root-secondarynamenode.pid
    -rw-r--r-- 1 root root    6 Apr 10 13:55 yarn-root-resourcemanager.pid
     
    drwxr-xr-x 4 root root 4096 Apr 10 14:52 Jetty_0_0_0_0_50070_hdfs____w2cu08
    drwxr-xr-x 4 root root 4096 Apr 10 14:52 Jetty_0_0_0_0_50090_secondary____y6aanv
    drwxr-xr-x 5 root root 4096 Apr 10 15:02 Jetty_master_8088_cluster____i4ls4w

    前三个文件是存放PID的文件,后三个Jetty_xxx格式的目录是Hadoop的web应用的临时目录,不是我们关心的。

    打开一个pid文件看看:

    [root@master tmp]# cat hadoop-root-namenode.pid 
    32169

    很简单,就保存了namenode进程的PID,再关闭namenode进程时就要从这个文件中读取PID。

    到这里问题已经愉快的解决了!

    但是,明知道pid文件放这里不安全,还不修改一下就显得我太懒了!

    修改pid文件存放目录,只需要在hadoop-daemon.sh脚本中添加一行声明即可:

    HADOOP_PID_DIR=/root/hadoop/pid  #第25行

    记住要先关闭Hadoop再修改,不然你修改完又无法关闭了!同样的道理,你还需要修改yarn-daemon.sh

    YARN_PID_DIR=/root/hadoop/pid

    然后执行start-dfs.sh start-yarn.sh 启动Hadoop。再去/root/hadoop/pid目录下看看:

    [root@master pid]# ll
    -rw-r--r-- 1 root root 5 Apr 10 14:52 hadoop-root-namenode.pid
    -rw-r--r-- 1 root root 5 Apr 10 14:52 hadoop-root-secondarynamenode.pid
    -rw-r--r-- 1 root root 5 Apr 10 15:02 yarn-root-resourcemanager.pid

    好了,从此再也不用担心出现no xxx to stop的警告了!

    /tmp目录的清理策略

    除了更换pid文件的保存路径外,我不由会想起另外一种解决思路,不让操作系统删除保存在/tmp目录下的pid文件不就可以了嘛!好的,那我们就来看看操作系统是怎么清理/tmp目录的。

    遇到这个问题之前,我也没关系过/tmp目录,度娘一下,得到答案。

    我们先来看一个重要的命令:

    tmpwatch

    tmpwatch指令可删除不必要的暂存文件,你可以设置文件超期时间,单位以小时计算。

    常用参数:
    -m 或–mtime 根据文件被更改时间
    -c 或–ctime 根据文件更改状态时间
    -M 或–dirtime 根据文件夹被更改时间
    -x 或–exclude=path 排除某路径
    -X 或–exclude-pattern=pattern 排除某规则下的路径

    /tmp作为临时文件夹,系统默认每天清理一次该目录。系统通过定时任务每天会执行一次/etc/cron.daily/tmpwatch这个脚本。其原理就是利用tmpwatch指令,设置清理策略。我们来看一下这个脚本内容:

    /etc/cron.daily/tmpwatch
    #! /bin/sh
    flags=-umc
    /usr/sbin/tmpwatch "$flags" -x /tmp/.X11-unix -x /tmp/.XIM-unix 
            -x /tmp/.font-unix -x /tmp/.ICE-unix -x /tmp/.Test-unix 
            -X '/tmp/hsperfdata_*' 10d /tmp
    /usr/sbin/tmpwatch "$flags" 30d /var/tmp
    for d in /var/{cache/man,catman}/{cat?,X11R6/cat?,local/cat?}; do
        if [ -d "$d" ]; then
            /usr/sbin/tmpwatch "$flags" -f 30d "$d"
        fi
    done

    代码的4~6行是一条语句,设置/tmp目录的清理策略. -x或-X是用来排除不清理的文件或目录,10d表示会删除最近10天没有被访问的文件(有的系统可能是240 ,表示240小时,也是10天)。

    好吧 ,10天不用就给删除了,Hadoop集群运行几十天了,当然也就找不到pid文件了。

    你有注意第6行代码中,被排除的文件吗 ?/tmp/hsperfdata_*,我们在上面解决问题时,第一次查看/tmp目录就有一个匹配此模式的文件:hsperfdata_root 。

    那么,想不让系统删除pid文件,比着榴莲画个瓢就行了。在tmpwatch脚本中增加一个排除条件即可:

    -X '/tmp/*.pid'

    不过,既然是临时目录,重要的文件就不要放这了,还是推荐第一种解决方式!


  • 相关阅读:
    Ink——一款使用React风格开发命令行界面应用(CLI App)的nodejs工具
    编程语言相关名词解释汇总
    使用Webpack对Css文件压缩处理的思考
    一种通过async/await实现函数同步执行的方式
    成长的道路上,我很幸运
    Todolist分别用React与Vue的实现与思考
    Unity 框架篇
    扇形技能指示器
    C# Socket和protoBuf新手村教程
    判断点在多边形内部
  • 原文地址:https://www.cnblogs.com/lukeguo/p/8824761.html
Copyright © 2011-2022 走看看