http://blog.csdn.net/pipisorry/article/details/51623195
因为lz的linux系统已经安装好了很多开发环境,可能下面的步骤有遗漏。
之前是在docker中配置的hadoop单机伪分布式[Hadoop:Hadoop单机伪分布式的安装和配置 ],并且在docker只有root用户,所有没有权限问题存在。
这里直接在linux下配置,主要是为了能用netbeans ide调试hadoop程序,并且使用的用户就是开机时登录的用户pika。
本教程配置环境:
ubuntu14.04(Ubuntu 12.04 /32位、64位都ok! lz是直接使用的双系统中的linux)
hadoop 2.6.4 (原生 Hadoop 2都ok!)
jdk1.7.0_101(应该1.6+应该都ok!)
基本环境配置
安装和配置Java环境
在主机上从Oracle官方网站下载对应版本的JDK安装包
$ sudo vim /etc/profile
第一行“...”的path末尾加上:${JAVA_HOME}/bin,后面export路径
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games"
export JAVA_HOME=/opt/jdk1.8.0_73
export JRE_HOME=${JAVA_HOME}/jre
export CLASSPATH=.:${JAVA_HOME}/lib:${JRE_HOME}/lib
export PATH=$PATH:${JAVA_HOME}/bin
$ sudo update-alternatives --install /usr/bin/java java /opt/jdk1.8.0_73/bin/java 300;
sudo update-alternatives --install /usr/bin/javac javac /opt/jdk1.8.0_73/bin/javac 300;
sudo update-alternatives --install /usr/bin/javah javah /opt/jdk1.8.0_73/bin/javah 300;
sudo update-alternatives --install /usr/bin/jar jar /opt/jdk1.8.0_73/bin/jar 300
. /etc/profile
测试是否安装成功
[email protected]:/#java -version
安装SSH、配置SSH无密码登陆
集群、单节点模式都需要用到 SSH (ssh must be installed and sshd must be running to use the Hadoop scripts that manage remote Hadoop daemons,而这并没有说一定要ssh localhost登录啊!!!lz亲测,没有ssh localhost登录一样可以运行hadoop程序,只要安装并运行了sshd就可以了),Ubuntu 默认已安装了 SSH client,还需要安装 SSH server:
pika:~$sudo apt-get install -y openssh-server
编辑sshd的配置文件pika:~$sudo vim /etc/ssh/sshd_config,将其中大概88行,UsePAM参数设置成“no”
启动sshd服务pika:~$sudo /etc/init.d/ssh start
#每次重启都要重新启动,所以要加入到profile中开机自启
pika:~$sudo vim /etc/profile
其中加入一行/etc/init.d/ssh start
查看ssh服务状态 pika:~$ps -e | grep ssh
29856 ? 00:00:00 sshd
安装后,可以使用如下命令登陆本机:ssh localhost
此时会有SSH首次登陆提示,输入 no,(如果输入yes再输入密码,这样就登陆到本机了,但这样登陆是需要每次输入密码的,我们需要配置成SSH无密码登陆比较方便,如果进去了首先退出刚才的 ssh)。
回到我们原先的终端窗口,然后利用 ssh-keygen 生成密钥,并将密钥加入到授权中:
exit # 退出刚才的 ssh localhost,或者用ctrl+d
cd ~/.ssh/ # 若没有该目录,请先执行一次ssh localhost
ssh-keygen -t rsa # 会有提示,都按回车就可以,如果已经存在,直接进入下一步就可以了(lz的就存在,说明以前已经用过这个)
cat ./id_rsa.pub >> ./authorized_keys # 加入授权,把id_rsa.pub 追加到授权的 key 里面去
最后退出ssh, ctrl+d
关于设置hadoop用户 (其实完全可以不用)
Hadoop的安装和配置
Hadoop 2 可以通过 http://mirror.bit.edu.cn/apache/hadoop/common/ 或者 http://mirrors.cnnic.cn/apache/hadoop/common/ 下载,一般选择下载最新的稳定版本,即下载 “stable” 下的 hadoop-2.x.y.tar.gz 这个格式的文件,这是编译好的,另一个包含 src 的则是 Hadoop 源代码,需要进行编译才可使用。lz下载的是hadoop-2.6.4。
安装Hadoop 至 /usr/local/ 中
下载hadoop到/usr/local并解压
pika:~$sudo wget http://mirror.bit.edu.cn/apache/hadoop/common/hadoop-2.6.4/hadoop-2.6.4.tar.gz -P /usr/local
pika:~$cd /usr/local/
pika:/usr/local$sudo tar -zxf hadoop-2.6.4.tar.gz
pika:/usr/local$sudo ln -s /usr/local/hadoop-2.6.4 /usr/local/hadoop #设置软链接,这样两个目录是一样的了
pika:/usr/local$ls /usr/local/hadoop
bin etc include lib libexec LICENSE.txt NOTICE.txt README.txt sbin share
sudo chown -R hadoop ./hadoop # -R递归修改文件所有者为hadoop
检查 Hadoop 是否可用
pika:/usr/local$hadoop/bin/hadoop version
Hadoop 2.6.4
Subversion https://git-wip-us.apache.org/repos/asf/hadoop.git -r 5082c73637530b0b7e115f9625ed7fac69f937e6
Compiled by jenkins on 2016-02-12T09:45Z
Compiled with protoc 2.5.0
From source with checksum 8dee2286ecdbbbc930a6c87b65cbc010
This command was run using /usr/local/hadoop-2.6.4/share/hadoop/common/hadoop-common-2.6.4.jar
Hadoop单机伪分布式配置
{如上所述,下面的安装和运行其实根本没用到ssh localhost登录,也可以运行!如果实在要ssh登录只用在start-dfs.sh执行前登录就可以了}
Hadoop 可以在单节点上以伪分布式的方式运行,Hadoop 进程以分离的 Java 进程来运行,节点既作为 NameNode 也作为 DataNode,同时,读取的是 HDFS 中的文件。
Hadoop 的配置文件位于 /usr/local/hadoop/etc/hadoop/ 中,伪分布式需要修改2个配置文件 core-site.xml 和 hdfs-site.xml 。Hadoop的配置文件是 xml 格式,每个配置以声明 property 的 name 和 value 的方式来实现。
Hadoop执行命令目录加入到path中
pika:~$sudo vim /etc/profile
PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games"
PATH="$PATH:${JAVA_HOME}/bin:${SPARK_HOME}/bin:${HADOOP_HOME}/bin:${HADOOP_HOME}/sbin"
export PATH
export JAVA_HOME=/opt/jdk1.8.0_73
export JRE_HOME=${JAVA_HOME}/jre
export CLASSPATH=.:${JAVA_HOME}/lib:${JRE_HOME}/
export CLASSPATH=$CLASSPATH:/usr/local/hadoop-2.6.4/etc/hadoop:/usr/local/hadoop-2.6.4/share/hadoop/common/lib/*:/usr/local/hadoop-2.6.4/share/hadoop/common/*:/usr/local/hadoop-2.6.4/share/hadoop/hdfs:/usr/local/hadoop-2.6.4/share/hadoop/hdfs/lib/*:/usr/local/hadoop-2.6.4/share/hadoop/hdfs/*:/usr/local/hadoop-2.6.4/share/hadoop/yarn/lib/*:/usr/local/hadoop-2.6.4/share/hadoop/yarn/*:/usr/local/hadoop-2.6.4/share/hadoop/mapreduce/lib/*:/usr/local/hadoop-2.6.4/share/hadoop/mapreduce/*:/usr/local/hadoop-2.6.4/contrib/capacity-scheduler/*.jar
export HADOOP_HOME=/usr/local/hadoop-2.6.4
export SPARK_HOME=/opt/spark
export PYSPARK_PYTHON=python3
Note: HADOOP_HOME必须使用实际目录,不能使用软链接!;lz之前配置过spark,里面有spark的配置,不用管,主要是加色的部分加上去就ok了。
pika:~$ . /etc/profile #下次重启后不用
pika:~$echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/opt/jdk1.8.0_73/bin:/opt/spark/bin:/usr/local/hadoop-2.6.4/bin:/usr/local/hadoop-2.6.4/sbin
改配置文件 core-site.xml和hdfs-site.xml
pika:~$cd /usr/local/hadoop
pika:/usr/local/hadoop$sudo vim etc/hadoop/core-site.xml
将当中的<configuration></configuration>修改成:
<configuration>
<property>
<name>hadoop.tmp.dir</name>
<value>file:/usr/local/hadoop/tmp</value>
<description>Abase for other temporary directories.</description>
</property>
<property>
<name>fs.defaultFS</name>
<value>hdfs://localhost:9000</value>
</property>
</configuration>
Note: 我去,设置了vim后,vim中粘贴都会自动缩进,所以可以先在gedit将前面的空格删了:^\s+。
同样修改配置文件 hdfs-site.xml:
pika:/usr/local/hadoop$sudo vim etc/hadoop/hdfs-site.xml
<configuration>
<property>
<name>dfs.replication</name>
<value>1</value>
</property>
<property>
<name>dfs.namenode.name.dir</name>
<value>file:/usr/local/hadoop/tmp/dfs/name</value>
</property>
<property>
<name>dfs.datanode.data.dir</name>
<value>file:/usr/local/hadoop/tmp/dfs/data</value>
</property>
</configuration>
Hadoop配置文件说明
Hadoop 的运行方式是由配置文件决定的(运行 Hadoop 时会读取配置文件),因此如果需要从伪分布式模式切换回非分布式模式,需要删除 core-site.xml 中的配置项。
此外,伪分布式虽然只需要配置 fs.defaultFS 和 dfs.replication 就可以运行,不过若没有配置 hadoop.tmp.dir 参数,则默认使用的临时目录为 /tmp/hadoo-hadoop,而这个目录在重启时有可能被系统清理掉,导致必须重新执行 format 才行。
同时也指定 dfs.namenode.name.dir 和 dfs.datanode.data.dir,否则在接下来的步骤中可能会出错。
配置完成后,执行 NameNode 的格式化
hadoop中配置JAVA_HOME
pika:~$sudo vim /usr/local/hadoop-2.6.4/libexec/hadoop-config.sh
在大概161行位置加上export JAVA_HOME=/opt/jdk1.8.0_73
$cd /usr/local/hadoop
pika:/usr/local/hadoop$sudo bin/hdfs namenode -format
成功的话,会看到 “successfully formatted” 和 “Exitting with status 0” 的提示,若为 “Exitting with status 1” 则是出错。
开启 NameNode 和 DataNode 守护进程
对hadoop安装目录执行命令对文件敞开权限,否则会出错Starting namenodes on [localhost] localhost: mkdir: cannot create directory ‘/usr/soft/hadoop-2.6.3/logs’: Permission denied
pika:~$sudo chown -R pika:pika /usr/local/hadoop-2.6.4
pika:~$sudo chmod u+w -R /usr/local/hadoop-2.6.4
Note: lz将hadoop目录所有权修改成了当前用户pika及用户组pika,并给目录递归加上的当前用户pika的写权限。当然也可以直接给所有用户都加上w权限:$sudo chmod a+w -R /usr/local/hadoop-2.6.4/,不过lz觉得这样可能会有安全隐患。
pika:~$start-dfs.sh
Note: 若出现SSH提示,输入yes即可
Note: 出现上面结果不一定就是说hadoop运行正确了,要通过下面的jps查看。
如果运行上面的start-dfs.sh出错,再次运行可能会出错,一般都是因为没有stop相关的程序。所以要通过stop-dfs.sh实现。
通过jps查看启动的Hadoop进程
启动完成后,可以通过命令 jps 来判断是否成功启动,若成功启动则会列出如下进程: “NameNode”、”DataNode” 和 “SecondaryNameNode”(如果 SecondaryNameNode 没有启动,请运行 sbin/stop-dfs.sh 关闭进程,然后再次尝试启动尝试)。如果没有 NameNode 或 DataNode ,那就是配置不成功,请仔细检查之前步骤,或通过查看启动日志排查原因。
pika:~$jps
通过web界面访问
如果是linux或者虚拟机配置的hadoop,成功启动后,可以访问 Web 界面 http://localhost:50070 查看 NameNode 和 Datanode 信息,还可以在线查看 HDFS 中的文件。
启动Hadoop可能的错误及解决
Hadoop无法正常启动的解决方法
一般可以查看启动日志来排查原因,注意几点:
启动时会提示形如 “DBLab-XMU: starting namenode, logging to /usr/local/hadoop/logs/hadoop-hadoop-namenode-DBLab-XMU.out”,其中 DBLab-XMU 对应你的机器名,但其实启动日志信息是记录在 /usr/local/hadoop/logs/hadoop-hadoop-namenode-DBLab-XMU.log 中,所以应该查看这个后缀为 .log 的文件;
每一次的启动日志都是追加在日志文件之后,所以得拉到最后面看,对比下记录的时间就知道了。
一般出错的提示在最后面,通常是写着 Fatal、Error、Warning 或者 Java Exception 的地方。
可以在网上搜索一下出错信息,看能否找到一些相关的解决方法。
如:
FATAL org.apache.hadoop.hdfs.server.namenode.NameNode: Failed to start namenode.
org.apache.hadoop.hdfs.server.common.InconsistentFSStateException: Directory /usr/local/hadoop-2.6.4/tmp/dfs/name is in an inconsistent state: storage directory does not exist or is not accessible.
这个错误是一般都是因为没有如上sudo vim etc/hadoop/hdfs-site.xml配置,或者是没有如上修改当前用户write目录的权限。
错误1:
启动时可能会出现如下 WARN 提示:WARN util.NativeCodeLoader: Unable to load native-hadoop library for your platform… using builtin-java classes where applicable。该 WARN 提示可以忽略,并不会影响正常使用(该 WARN 可以通过
编译 Hadoop 源码解决)。
错误2:
出错:Starting namenodes on [localhost]
localhost: Error: JAVA_HOME is not set and could not be found.
明明已经设置了,并且$ echo $JAVA_HOME
/opt/jdk1.8.0_91成功输出!
解决方案:pika:~$sudo vim /usr/local/hadoop-2.6.4/libexec/hadoop-config.sh,具体如上。
错误3:
启动 Hadoop 时提示 Could not resolve hostname
如果启动 Hadoop 时遇到输出非常多“ssh: Could not resolve hostname xxx”的异常情况
这个并不是 ssh 的问题,可通过设置 Hadoop 环境变量来解决。首先按键盘的 ctrl + c 中断启动,然后在 ~/.bashrc 中,增加如下两行内容(设置过程与 JAVA_HOME 变量一样,其中 HADOOP_HOME 为 Hadoop 的安装目录):
export HADOOP_HOME=/usr/local/hadoop
export HADOOP_COMMON_LIB_NATIVE_DIR=$HADOOP_HOME/lib/native
执行 source ~/.bashrc 使变量设置生效,然后再次执行 ./sbin/start-dfs.sh 启动 Hadoop。
错误4:DataNode 没有启动
一般情况下,若是 DataNode 没有启动,可尝试如下的方法(注意这会删除 HDFS 中原有的所有数据,如果原有的数据很重要请不要这样做):
./sbin/stop-dfs.sh # 关闭
rm -r ./tmp 删除 tmp 文件,注意这会删除 HDFS 中原有的所有数据
./bin/hdfs namenode -format 重新格式化 NameNode
./sbin/start-dfs.sh # 重启
Hadoop单机伪分布式运行实例
单机模式grep 例子读取的是本地数据,伪分布式读取的则是 HDFS 上的数据。这里我们还要自己写java代码,并在java代码中引入hadoop packages。
如果你是自己创建的用户,并且没有用户目录的话,要使用 HDFS,首先需要在 HDFS 中创建用户目录:
./bin/hdfs dfs -mkdir -p /user/hadoop
接着将文件复制到分布式文件系统中。
我们使用的是 hadoop 用户,并且已创建相应的用户目录 /user/hadoop ,因此在命令中就可以使用相对路径如 input,其对应的绝对路径就是 /user/hadoop/input
添加hadoop classpath
这一步已经在上面的path环境配置中配置过了
pika:/media/pika/files/mine/java_workspace/BDMS/src/hw2$hadoop classpath
/usr/local/hadoop-2.6.4/etc/hadoop:/usr/local/hadoop-2.6.4/share/hadoop/common/lib/*:/usr/local/hadoop-2.6.4/share/hadoop/common/*:/usr/local/hadoop-2.6.4/share/hadoop/hdfs:/usr/local/hadoop-2.6.4/share/hadoop/hdfs/lib/*:/usr/local/hadoop-2.6.4/share/hadoop/hdfs/*:/usr/local/hadoop-2.6.4/share/hadoop/yarn/lib/*:/usr/local/hadoop-2.6.4/share/hadoop/yarn/*:/usr/local/hadoop-2.6.4/share/hadoop/mapreduce/lib/*:/usr/local/hadoop-2.6.4/share/hadoop/mapreduce/*:/usr/local/hadoop-2.6.4/contrib/capacity-scheduler/*.jar
Note:要将hadoop classpath输出加入到CLASSPATH中,Hadoop provides a convenient utility to get the CLASSPATH information you need. Run "hadoop classpath" This should give you the information you need set your classpath for compiling your code.否则java代码中import package org.apache.hadoop.*会出错:javac .java error: package org.apache.hadoop.conf does not exist...[package org.apache.hadoop.fs does not exist]
#启动hadoop并将input文件copy到hdfs中
pika:~$hdfs dfs -ls /
pika:~$hdfs dfs -mkdir -p /pika/input
pika:~$hdfs dfs -ls /
drwxr-xr-x - pika supergroup 0 2016-06-10 19:22 /pika
将输入文件copy到hadoop hdfs文件系统中供其使用(.java文件是可以不用copy进去的)
pika:~$hdfs dfs -put /media/pika/files/mine/java_workspace/BDMS/src/hw2/*input* /pika/input
pika:~$hdfs dfs -ls /pika/input
-rw-r--r-- 1 pika supergroup 165 2016-06-10 19:28 /pika/input/example-input.txt
drwxr-xr-x - pika supergroup 0 2016-06-10 19:28 /pika/input/part1-input
Note: /media/pika/files/mine/java_workspace/BDMS/src/hw2/目录下的文件有哪些可以在这里下载[avg-time hadoop程序]
#编译执行java的hadoop程序
pika:~$cd /media/pika/files/mine/java_workspace/BDMS/src/hw2/
pika:/media/pika/files/mine/java_workspace/BDMS/src/hw2$rm -f *.class *.jar#移除已有的java编译文件
pika:/media/pika/files/mine/java_workspace/BDMS/src/hw2$ javac AvgTime.java
pika:/media/pika/files/mine/java_workspace/BDMS/src/hw2$jar cfm AvgTime.jar AvgTime-manifest.txt AvgTime*.class
pika:/media/pika/files/mine/java_workspace/BDMS/src/hw2$hdfs dfs -rm -f -r /pika/output #移除已有的output文件夹目录
pika:/media/pika/files/mine/java_workspace/BDMS/src/hw2$hadoop jar ./AvgTime.jar /pika/input/example-input.txt /pika/output #执行hadoop程序
pika:/media/pika/files/mine/java_workspace/BDMS/src/hw2$hdfs dfs -cat ‘/pika/output/part-*‘ #查看输出
1.2.3.4 18811001100 2 28.500
alpha 1.2.3.4 2 20.200
beta alpha 2 4.100
Note: Hadoop 运行程序时,输出目录不能存在,否则会提示错误 “org.apache.hadoop.mapred.FileAlreadyExistsException: Output directory hdfs://localhost:9000/user/hadoop/output already exists” ,因此若要再次执行,需要执行如下命令删除 output 文件夹: ./bin/hdfs dfs -rm -r output
运行 Hadoop 程序时,为了防止覆盖结果,程序指定的输出目录(如 output)不能存在,否则会提示错误,因此运行前需要先删除输出目录。在实际开发应用程序时,可考虑在程序中加上如下代码,能在每次运行时自动删除输出目录,避免繁琐的命令行操作:
Configuration conf = new Configuration();
Job job = new Job(conf);
/* 删除输出目录 */
Path outputPath = new Path(args[1]);
outputPath.getFileSystem(conf).delete(outputPath, true);
from: http://blog.csdn.net/pipisorry/article/details/51623195
ref: