SSH

一:hadoop集群SSH配置:

( 说明:hadoop@hadoop~]$ssh-keygen  -t  rsa

这个命令将为hadoop上的用户hadoop生成其密钥对,询问其保存路径时直接回车采用默认路径,当提示要为生成的密钥输入passphrase的时候,直接回车,也就是将其设定为空密码。生成的密钥对id_rsa,id_rsa.pub,默认存储在/home/hadoop/.ssh目录下然后将 id_rsa.pub的内容复制到每个机器(也包括本机)的/home/dbrg/.ssh/authorized_keys文件中,如果机器上已经有 authorized_keys这个文件了,就在文件末尾加上id_rsa.pub中的内容,如果没有authorized_keys这个文件,直接复制过去就行.)


id_rsa.pub这个公钥,需要放在每个用户的文件夹.ssh中。

3) 首先设置namenode的ssh为无需密码的、自动登录。

切换到hadoop用户

$ su hadoop

cd /home/hadoop

$ ssh-keygen -t rsa然后一直按回车

完成后,在home跟目录下会产生隐藏文件夹.ssh

$ cd .ssh

之后ls 查看文件

cp id_rsa.pub authorized_keys

测试:

ssh localhost发现链接成功,并且无需密码。

 

 

4 ) 复制到node2 和node3 上

[hadoop@hadoop .ssh]$ scp authorized_keys  node2:/home/hadoop/.ssh/

[hadoop@hadoop .ssh]$ scp authorized_keys  node3:/home/hadoop/.ssh/

输入 yes 来继续。这会把该服务器添加到你的已知主机的列表中
The authenticity of host ‘test (192.168.9.111)’ can’t be established.
RSA key fingerprint is 03:e0:30:cb:6e:13:a8:70:c9:7e:cf:ff:33:2a:67:30.
Are you sure you want to continue connecting (yes/no)?

  • 这里会提示输入密码,输入hadoop账号密码就可以了。

改动你的 authorized_keys 文件的许可权限:
[hadoop@hadoop .ssh]$chmod 644 authorized_keys

检查下能不能配置成功,从hadoop机器上ssh到node2和node3,如果不须要输入密码则配置成功,如果还须要请检查上面的配置能不能正确。

二:hadoop-streaming使用

Hadoop streaming是Hadoop的一个工具, 它帮助用户创建和运行一类特殊的map/reduce作业, 这些特殊的map/reduce作业是由一些可执行文件或脚本文件充当mapper或者reducer。例如: 

$HADOOP_HOME/bin/hadoop jar $HADOOP_HOME/hadoop-streaming.jar \
-input myInputDirs \
-output myOutputDir \
-mapper /bin/cat \
-reducer /bin/wc

Streaming工作原理

在上面的例子里,mapper和reducer都是可执行文件,它们从标准输入读入数据(一行一行读),并把计算结果发给标准输出。Streaming工具会创建一个Map/Reduce作业,并把它发送给合适的集群,同时监视这个作业的整个执行过程。

如果一个可执行文件被用于mapper,则在mapper初始化时,每一个mapper任务会把这个可执行文件作为一个单独的进程启动。 mapper任务运行时,它把输入切分成行并把每一行提供给可执行文件进程的标准输入。同时,mapper收集可执行文件进程标准输出的内容,并把收到的每一行内容转化成key/value对,作为mapper的输出。默认情况下,一行中第一个tab之前的部分作为key,之后的(不包括tab)作为value。如果没有tab,整行作为key值,value值为null。不过,这可以定制,在下文中将会讨论如何自定义key和value的切分方式。

如果一个可执行文件被用于reducer,每个reducer任务会把这个可执行文件作为一个单独的进程启动。 Reducer任务运行时,它把输入切分成行并把每一行提供给可执行文件进程的标准输入。同时,reducer收集可执行文件进程标准输出的内容,并把每一行内容转化成key/value对,作为reducer的输出。默认情况下,一行中第一个tab之前的部分作为key,之后的(不包括tab)作为value。在下文中将会讨论如何自定义key和value的切分方式。

这是Map/Reduce框架和streaming mapper/reducer之间的基本通信协议。

用户也可以使用java类作为mapper或者reducer。上面的例子与这里的代码等价:

$HADOOP_HOME/bin/hadoop jar $HADOOP_HOME/hadoop-streaming.jar \
-input myInputDirs \
-output myOutputDir \
-mapper org.apache.hadoop.mapred.lib.IdentityMapper \
-reducer /bin/wc
用户可以设定stream.non.zero.exit.is.failure true 或false 来表明streaming task的返回值非零时是 Failure 还是Success。默认情况,streaming task返回非零时表示失败。

将文件打包到提交的作业中

任何可执行文件都可以被指定为mapper/reducer。这些可执行文件不需要事先存放在集群上;如果在集群上还没有,则需要用-file选项让framework把可执行文件作为作业的一部分,一起打包提交。例如:

$HADOOP_HOME/bin/hadoop jar $HADOOP_HOME/hadoop-streaming.jar \
-input myInputDirs \
-output myOutputDir \
-mapper myPythonScript.py \
-reducer /bin/wc \
-file myPythonScript.py

上面的例子描述了一个用户把可执行python文件作为mapper。其中的选项“-file myPythonScirpt.py”使可执行python文件作为作业提交的一部分被上传到集群的机器上。

除了可执行文件外,其他mapper或reducer需要用到的辅助文件(比如字典,配置文件等)也可以用这种方式打包上传。例如:

$HADOOP_HOME/bin/hadoop jar $HADOOP_HOME/hadoop-streaming.jar \
-input myInputDirs \
-output myOutputDir \
-mapper myPythonScript.py \
-reducer /bin/wc \
-file myPythonScript.py \
-file myDictionary.txt
Streaming选项与用法
只使用Mapper的作业
有时只需要map函数处理输入数据。这时只需把mapred.reduce.tasks设置为零,Map/reduce框架就不会创建reducer任务,mapper任务的输出就是整个作业的最终输出。

为了做到向下兼容,Hadoop Streaming也支持“-reduce None”选项,它与“-jobconf mapred.reduce.tasks=0”等价。


1:当mapper和reducer是java程序时,必须打包成jar文件,而如果是python或者shell脚本时,则不需要。

因java是预编译的,必须编译成class文件才能运行。

而python是直接运行时,运行streaming命令时,会把脚本提交到集群中去。 

java的class文件或者python文件  都可以通过-file  Optional分发本地文件,别用于向计算节点分发本地文件、HDFS文件和HDFS压缩文件。

就比如之前做hadoop2hbase.jar一样,只要在当前运行的机器里放一个jar包,在当前目录运行,集群会自动分发这个jar包。


hadoop命令行老是给出这个提示:WARNING: org.apache.hadoop.metrics.jvm.EventCounter is deprecated。

需要把hadoop的conf下log4j文件改掉:只需要将 一个参数值从 org.apache.hadoop.metrics.jvm.EventCounter 修改为 org.apache.hadoop.log.metrics.EventCounter 即可。


4个部分(stack segment、heap segment、code segment、data segment) 
当我们在程序中,申明一个局部变量的时候,此变量就存放在了 stack segment(栈)当中; 
当new 一个对象的时候,此对象放在了heap segment(堆)当中; 
而static 的变量或者字符串常量 则存在在 data segment(数据区)中; 
那么类中方法的话,是存在在 code segment(代码区)中了。


接口就是提供一种统一的'协议',而接口中的属性也属于'协议'中的成员.它们是公共的,静态的,最终的常量.相当于全局常量.
抽象类是不'完全'的类,相当于是接口和具体类的一个中间层.即满足接口的抽象,也满足具体的实现.
如果接口可以定义变量,但是接口中的方法又都是抽象的,在接口中无法通过行为来修改属性。有的人会说了,没有关系,可以通过实现接口的对象的行为来修改接口中的属性。这当然没有问题,但是考虑这样的情况。如果接口A中有一个public访问权限的静态变量a。按照java的语义, 我们可以不通过实现接口的对象来访问变量a,通过A.a = xxx;就可以改变接口中的变量a的值了。正如抽象类中是可以这样做的,那么实现接口A的所有对象也都会自动拥有这一改变后的a的值了,也就是说一个地方改变了a,所有这些对象中a的值也都跟着变了。这和抽象类有什么区别呢,怎么体现接口更高的抽象级别呢,怎么体现接口提供的统一的协议呢,那还要接口这种抽象来做什么呢?所以接口中不能出现变量,如果有变量,就和接口提供的统一的抽象这种思想是抵触的。所以接口中的属性必然是常量,只能读不能改,这样才能为实现接口的对象提供一个统一的属性。
通俗的讲,你认为是要变化的东西,就放在你自己的实现中,不能放在接口中去,接口只是对一类事物的属性和行为更高层次的抽象。

接口中的属性默认是public static final 的,而抽象类中的属性和类中的属性完全一样。


HashSet和HashMap:

当在HashMap中添加key-value对,由其key的hashCode()返回值决定改key-value对的存储位置,当key-value对的key的hashCode()返回值相同时,key-value对的value将由key通过eqauls()比较值决定是采用覆盖行为(返回true)(key不做改变),还是产生key-value链(返回false)。
Java代码   收藏代码
  1. import java.util.*;  
  2. class Name  
  3. {  
  4.     private String first;  
  5.     private String last;  
  6.     public Name(String first, String last)   
  7.     {  
  8.         this.first = first;  
  9.         this.last = last;  
  10.     }  
  11.     //根据first判断两个Name是否相等  
  12.     public boolean equals(Object o)   
  13.     {  
  14.         if (this == o)  
  15.         {  
  16.             return true;  
  17.         }  
  18.         if (o.getClass() == Name.class)  
  19.         {  
  20.             Name n = (Name)o;  
  21.             return n.first.equals(first);  
  22.         }  
  23.         return false;  
  24.     }  
  25.     //根据first计算Name对象的hashCode()返回值  
  26.     public int hashCode()  
  27.     {  
  28.         return first.hashCode();  
  29.     }  
  30.     public String toString()  
  31.     {  
  32.         return "Name[first=" + first + ", last=" + last + "]";  
  33.     }  
  34. }  
  35. public class HashSetTest2  
  36. {  
  37.     public static void main(String[] args)   
  38.     {  
  39.         HashMap set = new         HashMap();   
  40.         set.put(new Name("abc" , "123"),"1111111");  
  41.         set.put(new Name("abc" , "456"),"2222222");  
  42.         System.out.println(set);  
  43.     }  
  44. }  
 输出:
{Name[first=abc, last=123]=2222222}
即key没变,value变了。

HashSet的实现只是封装了一个HashMap对象来存储所有的集合元素。所有放入HashSet中的集合元素实际上由HashMap的key来保存,而HashMap的value则存储了一个PRESENT,它是一个静态的Object对象。
由于HashSet的add()方法添加集合元素时实际上转变为调用HashMap的put()方法添加key-value对,当新放入HashMap的key-value对中key与集合中原有key-value对中的key相同(hashCode()返回值相等,通过eqauls()比较值也相等)时,新添加的key-value对的value将覆盖原来key-value对的value,但key不会有任何改变。因此,如果向HashSet中添加一个已经存在的元素,新添加的集合元素(底层由HashMap的key保存)不会覆盖已有的集合元素。
把上面代码main方法中改为:
HashSet set = new HashSet();
set.add(new Name("abc" , "123"));
set.add(new Name("abc" , "456"));
System.out.println(set);
则输出:
[Name[first=abc, last=123]]
即key没变


注意:在试图把某个对象当成HashMap的key,或者试图将这个类的对象放入HashSet中保存时,重写该类的equals(Object obj)方法和hashCode()方法很重要, 而且这两个方法的返回值必须一致。当该类的两个hashCode()返回值相同时,它们通过equals(Object obj)方法比较也应该返回true。通常来说,所有参与计算hashCode()返回值的关键属性,都应该用于作为equals(Object obj)比较的标准。
例如下面代码运行显示的是false,那是因为没有重写hashCode()方法。
Java代码   收藏代码
  1. import java.util.*;  
  2. /** 
  3.  * Description: 
  4.  * 
    网站: 疯狂Java联盟 
     
  5.  * 
    Copyright (C), 2001-2010, Yeeku.H.Lee
     
  6.  * 
    This program is protected by copyright laws.
     
  7.  * 
    Program Name:
     
  8.  * 
    Date:
     
  9.  * @author  Yeeku.H.Lee [email protected] 
  10.  * @version  1.0 
  11.  */  
  12. class Name  
  13. {  
  14.     private String first;  
  15.     private String last;  
  16.     public Name(String first, String last)   
  17.     {  
  18.         this.first = first;  
  19.         this.last = last;  
  20.     }  
  21.     public boolean equals(Object o)   
  22.     {  
  23.         if (this == o)  
  24.         {  
  25.             return true;  
  26.         }  
  27.         if (o.getClass() == Name.class)  
  28.         {  
  29.             Name n = (Name)o;  
  30.             return n.first.equals(first)  
  31.                 && n.last.equals(last);  
  32.         }  
  33.         return false;  
  34.     }  
  35. }  
  36. public class HashSetTest  
  37. {  
  38.     public static void main(String[] args)   
  39.     {  
  40.         Set s = new HashSet();  
  41.         s.add(new Name("abc""123"));  
  42.         System.out.println(  
  43.             s.contains(new Name("abc""123")));  
  44.     }   
  45. }  

Linux vim复制粘贴:

最基本的复制是 y,粘贴是 p,剪切是 d。
yy复制游标所在行整行。或大写一个Y。 

2yy或y2y复制两行。 ㄟ ,请举一反三好不好! :-) 
y^复制至行首,或y0。不含游标所在处字元。 
y$复制至行尾。含游标所在处字元。 
yw复制一个word。 
y2w复制两个字(单词)。 
yG复制至档尾。 
y1G复制至档首。 
p小写p代表贴至游标后(下)。 
P大写P代表贴至游标前(上)。
如果只是想使用系统粘贴板的话直接在输入模式按Shift+Inset就可以了




你可能感兴趣的:(hadoop)