本文主要讲解三个问题:
      1 使用Java编写MapReduce程序时,如何向map、reduce函数传递参数。
      2 使用Streaming编写MapReduce程序(C/C++, Shell, Python)时,如何向map、reduce脚本传递参数。
      3 使用Streaming编写MapReduce程序(C/C++, Shell, Python)时,如何向map、reduce脚本传递文件或文件夹。
         (1) streaming 加载本地单个文件
         (2) streaming 加载本地多个文件
         (3) streaming 加载本地目录
         (4) streaming编程时在mapreduce脚本中读 hdfs 文件
         (5) streaming编程时在mapreduce脚本中读 hdfs 目录
 
1.  Java编写MapReduce程序时,如何向map、reduce函数传递参数

我开始使用如下方式进行传递.

在主类中声明两个静态变量, 然后在 main 函数中给变量赋值, 试图在 map和reduce函数中获得变量的值。
代码结构类似如下:

 
 
 
 
提交到集群运行发现在 map 和 reduce函数中, 静态变量MaxScore的值始终是初值1。
于是试图在主类的静态区中给变量赋值 (因为静态区中的代码比main中的代码要先执行), 仍是不成功, MaxScore的值始终是初值1。
将上述代码在 单机hadoop上运行, 结果正常, map 函数中能获得变量的值。
思考是这个原因: 在提交作业到hadoop集群后,mapper类和reducer类就到各个 tasktracker上去运行了, 与主类独立, 不能交互。
因此,上述往 map 和 reduce 函数传参数的方法实在太天真。
于是想到其它一些方法: 例如将参数写入hdfs文件中, 然后在 mapper 和 reducer 类的 run方法中读取文件, 并将值读到相应变量,这是可行的,但是方法较复杂,代码如下:

上述方法尽管可用, 但是不是常规方法, 下面介绍常用的方法:
(1) 通过 Configuration 来传递参数
在main函数中调用set方法设置参数, 例如:

在mapper中通过上下文context来获取当前作业的配置, 并获取参数, 例如:

注: context 很有用, 能获取当前作业的大量信息,例如上面就获取了任务ID.
 
(2) 利用org.apache.hadoop.io.DefaultStringifier类

示例:

main中:

Configuration conf = new Configuration();

Text maxscore = new Text("12989");

DefaultStringifier.store(conf, maxscore ,"maxscore");

这样,Text对象maxscore就以“maxscore”作为key存储在conf对象中了,然后在map和reduce函数中调用load的方法便可以把对象读出。

mapper获取:

Configuration conf = context.getConfiguration()

Text out = DefaultStringifier.load(conf, "maxscore", Text.class);

需要说明的是,这个需要传递的对象必须要先实现序列化的接口,Hadoop的序列化是通过Writable接口来实现的

(2) 参考自:http://blog.sina.com.cn/s/blog_6b7cf18f0100x9jg.html

2.  编写 Streaming 程序时,如何向map、reduce函数传递参数

可以通过 streaming 的 cmdenv 选项设置环境变量,然后在 map 和 reduce 脚本中获取环境变量。

可参考 << hadoop streaming 高级编程 >>

http://dongxicheng.org/mapreduce/hadoop-streaming-advanced-programming/

(0) 作业提交脚本:

#!/usr/bin/env bash

max_read_count=${array[0]}

min_read_count=${array[1]}

max_write_count=${array[2]}

min_write_count=${array[3]}

hadoop jar $HADOOP_HOME/contrib/streaming/hadoop-0.20.2-streaming.jar \

-D mapred.reduce.tasks=1

-input $input \

-output $output  \

-mapper $mapper_script \

-file $map_file  \

-reducer $reducer_script \

-file $reduce_file \

-cmdenv "max_read_count=${array[0]}" \      # 设置环境变量   max_read_count .

-cmdenv "min_read_count=${array[1]}" \       # 多个变量时请多次使用 -cmdenv

-cmdenv "max_write_count=${array[2]}" \

-cmdenv "min_write_count=${array[3]}"

(1) Python mapper.py

#!/usr/bin/env python

import sys

import os

min_r_count = float(os.environ.get('min_read_count')) # get environment variables.

max_r_count = float(os.environ.get('max_read_count'))

min_w_count = float(os.environ.get('min_write_count'))

max_w_count = float(os.environ.get('max_write_count'))

(2)Shell mapper.sh

#!/usr/bin/env bash

while read line  # 读入行

do

a=$line

done

echo $min_read_count $max_read_count  # get environment variables.

(3)C/C++ mapper.c

#include

#include

int main(int argc, char *argv[], char *env[])

{

double min_r_count;

int i = 0;

for (i = 0; env[i] != NULL; i++) // env[i] 存储了环境变量, 每项的值为此种形式: PATH=******, 所以需要截取变量值

{

if( strstr(env[i], "PATH=") ) {

char *p =NULL;

p = strstr(env[i], "=");

if( (p-env[i]) == 4 )

printf("%s\n", ++p); // 获取 PATH 环境变量

}

if( strstr(env[i], "min_write_count=") ) {

char *p =NULL;

p = strstr(env[i], "=");

if( (p-env[i]) == strlen("min_write_count") )

printf("%s\n", ++p); // 获取  min_write_count  环境变量

}

}

char eachLine[200]={0};

while(fgets(eachLine, 199, stdin)) // read line from stdin

{

printf("%s", eachLine);

}

}


注意:
    Hadoop执行命令时的选项有顺序的, 顺序是 bin/hadoop command [genericOptions] [commandOptions]. 
    对于streaming, -D 属于genericOptions, 即hadoop的通用选项, 所以必须写在前面.
    Streaming 的所有选项可以参考:  
    hadoop jar $HADOOP_HOME/contrib/streaming/hadoop-0.20.2-streaming.jar -info
 
3.  编写 Streaming 程序时,如何向map、reduce函数传递文件或文件夹。

(1) streaming 加载本地单个文件

streaming 支持 -file 选项, 可以把 -file 后面的本地文件(注意是本地文件)打包成作业提交的一部分, 即打包到作业的jar文件当中, 这样在mapreduce脚本中就可以像访问本地文件一样访问打包的文件了.

实例:

作业提交文件 run.sh

mapper.py

注意:在提交作业时使用的是 -file logs/wbscoretest.log 指定需要加载的文件. 在 map 脚本中只需要直接读取文件 wbscoretest.log 即可, 不需要写 logs/wbscoretest.log, 因为只加载了文件 wbscoretest.log, 而不会加载 logs 目录和

wbscoretest.log 文件.

(2) streaming 加载本地多个文件

(3) streaming 加载本地目录 ( 若加载多个目录,用逗号隔开,-files dir1, dir2, dir3 )

使用streaming的 -file 选项不能加载本地目录, 我实验是如此.

我们可以使用 hadoop 的通用选项 -files 来加载本地目录, 加载成功后在mapreduce脚本中可以像访问本地目录一样访问加载的目录.

实际应用中,我们在编写 分词MapReduce作业时需要加载分词词典,就使用该方法.

作业提交脚本:

map 脚本: 读取目录下的文件.

加载多个目录:

注意:多个目录之间用逗号隔开,且不能有空格,否则会出错,这个限制太蛋疼了。

例如:

(4) streaming编程时在mapreduce脚本中读 hdfs 文件

使用 -files 选项, 后面跟需要读的 hdfs 文件路径. 这样在 mapreduce 脚本中就可以直接通过文件名来访问该文件.

作业提交脚本:

map脚本:

如果需要加载大文件, 我们可以将文件先上传到 hdfs 中, 然后在 mapreduce 脚本中读取 hdfs 文件.

(5) streaming编程时在mapreduce脚本中读 hdfs 目录

使用 -files 选项, 后面跟需要读的 hdfs 目录. 这样在 mapreduce 脚本中就可以像访问本地目录一样访问该目录.

作业提交脚本:

map脚本:  直接读取 tmp_kentzhan 目录.

如何向map和reduce脚本传递参数,加载文件和目录的更多相关文章

  1. 【hadoop】如何向map和reduce脚本传递参数,加载文件和目录

    本文主要讲解三个问题:       1 使用Java编写MapReduce程序时,如何向map.reduce函数传递参数.       2 使用Streaming编写MapReduce程序(C/C++ ...

  2. (转)如何向map和reduce脚本传递参数

    [MapReduce] 如何向map和reduce脚本传递参数,加载文件和目录 分类: hadoop2014-04-28 21:30 1553人阅读 评论(0) 收藏 举报 hadoop 本文主要讲解 ...

  3. python 脚本传递参数

    python查找指定字符 #!/usr/bin/env python import sys import re f = open("log.txt", "rb" ...

  4. PowerShell脚本传递参数

    在编写PowerShell脚本的时候,可以通过给变量赋值的方法输出想要的结果,但这样的话,需要改动脚本内容.其实也可以在脚本中定义参数,然后再在执行脚本的时候对参数赋值,而无需改动脚本内容. 在Pow ...

  5. linux shell编程指南第二十章------向脚本传递参数

    前面已经讲到如何使用特定变量$ 1 . . $ 9向脚本传递参数.$ #用于统计传递参数的个数.可 以创建一个u s a g e语句,需要时可通知用户怎样以适当的调用参数调用脚本或函数. 简单地说,下 ...

  6. shell调用python脚本,并且向python脚本传递参数

    1.shell调用python脚本,并且向python脚本传递参数: shell中: python test.py $para1 $para2 python中: import sys def main ...

  7. 分发系统介绍、expect脚本远程登录、expect脚本远程执行命令、expect脚本传递参数

    7月19日任务 20.27 分发系统介绍20.28 expect脚本远程登录20.29 expect脚本远程执行命令20.30 expect脚本传递参数 20.27 分发系统介绍 公司业务逐渐扩大时, ...

  8. Linux centosVMware运行告警系统、分发系统-expect讲解、自动远程登录后,执行命令并退出、expect脚本传递参数、expect脚本同步文件、指定host和要同步的文件、shell项目-分发系统-构建文件分发系统、分发系统-命令批量执行

    一运行告警系统 创建一个任务计划crontab -e 每一分钟都执行一次 调试时把主脚本里边log先注释掉 再次执行 没有发现502文件说明执行成功了,每日有错误,本机IP 负载不高 二.分发系统-e ...

  9. 学习加密(四)spring boot 使用RSA+AES混合加密,前后端传递参数加解密

      学习加密(四)spring boot 使用RSA+AES混合加密,前后端传递参数加解密 技术标签: RSA  AES  RSA AES  混合加密  整合   前言:   为了提高安全性采用了RS ...

随机推荐

  1. 学习 nginx (持续更新)

    什么是代理与反向代理,有什么应用场景? 平常经常听别人说代理与反向代理,那么这二者到底有什么区别呢? 代理 场景:我需要访问一个服务器C,但是由于某些原因我无法访问到它,(典型的就是你FQ,然后fai ...

  2. 收集的几个好用的maven mirror

    <mirrors> <mirror> <id>jboss-public-repository-group</id> <mirrorOf>ce ...

  3. Java Web中Kaptcha实现验证码

    首先进行导入相应的jar包: 1.如果是maven项目,在你的pom文件中进行添加如下代码,将自动下载jar包到你的工程中: <dependency>            <gro ...

  4. lvs fullnat部署手册(一)fullnat内核编译篇

    标签:kernel rpm lvs fullnat 原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://shanks.blog.51c ...

  5. 利用CSS变量实现悬浮效果

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  6. session、cookie、viewstate

    session的用法 定义:保存在服务器内存的数据,sesson 只应该应用在需要跨页面且与每个访问用户相关的变量和对象存储上,session在默认情况下20分钟就过期,在页面之中最好不要过多使用,因 ...

  7. ansible配置文件 ansible.cfg的一点说明

    ansible配置文件 ansible.cfg的一点说明 > ansible --version ansible 2.1.1.0 config file = /etc/ansible/ansib ...

  8. windows环境下使用MySQL导入数据乱码报错的解决办法

    Linux及Mac系统下使用source xxx.sql 可直接导入测试数据(注意必须先切换到当前xxx.sql的目录下), 但在Windows环境下导入会出现乱码报错的情况, 主要是因为编码的问题, ...

  9. New Concept English three(21)

    27W 59 Boxing matches were very popular in England two hundred years ago. In those days, boxers foug ...

  10. PostgreSQL copy命令使用记录

    上篇写到用pg_bulkload来导入数据,但是实际的环境是solaris,pg_bulkload还不支持,于是用copy的方式,下面附上脚本 -bash-4.1$ cat copy.sh #!/bi ...