最近要在10几台机器上安装hadoop。对于这种繁复而重复的工作,一步步的打命令行,对于程序员来说是一件不能忍的事情。所以我就琢磨着怎么写一个脚本来自动安装hadoop。

任务: 在10几台机器上中的任意一台执行脚本,即可安装好hadoop。

条件: 每台机器的用户名和密码都是一样的。每台机器都配置好了ssh,能够远程登录。

解决思路:

  1. 首先读取配置文件,读取到节点的ip和想要的机器名字,然后修改好本地hadoop的配置文件。

  2. 然后读取配置文件,复制所有文件到每个节点的安装的路径。(利用scp命令可以远程复制)

  3. 然后读取配置文件,自动ssh到每个节点做一些配置工作,包括配置hadoop和JDK 环境变量、生成ssh-key。

  4. ssh到主节点,将每个节点(包括主节点自己)生成的public key 都复制并追加到自己的authorized_keys. 然后把这个authorized_keys分发到每个节点。

这样就配置好了hadoop。

  题外话,介绍一下 ssh-keygen。ssh-keygen是一个ssh用于生成密钥的命令。用途是用于免密码登录。它会生成两个密钥,一个是公钥,一个是私钥。比如A 机器生成了pubKeyA,priKeyB。然后A 把pubKeyA给了机器B ,然后机器B 就可以无密码登录机器A 了。

在上面的步骤中,主要的难题是。

1. 对于步骤一,主要难题在于怎么用shell读取配置文件。由于我也之前没写过shell,所以Shell的循环和if 语句和字符串处理也卡了不少时间。

# 这段代码是怎么从hosts的节点配置文件中读取节点的信息
# hosts的格式如下
# 192.168.1.100 master
# 192.168.1.101 slave1
# 192.168.1.102 slave2
# ...
while read line
do
echo $line
ip=`echo $line | cut -d" " -f1`
name=`echo $line | cut -d" " -f2`
if [ ! -z $ip ]; then
echo $name
if [[ $name == maste* ]]; then
echo "$name" >> ../hadoop-1.2./conf/masters
elif [[ $name == slave* ]]; then
echo "$name" >> ../hadoop-1.2./conf/slaves 
fi
fi
done < hosts

2. 对于步骤2,由于刚开始节点直接没有实现无密码ssh,所以scp命令需要输入密码,所以怎么实现自动输入密码实在是一个棘手的问题。我搜索之后,发现一个工具叫expect。

 expect工具就像bash一样有自己的语法,然后有自己的命令。它的语法是基于TCL这种脚本语言(我也没听过),看帮助可以直接man expect。我觉得主要需要知道的expect命令是spawn,expect,exp_continue这三个。

#!/usr/bin/expect
# expect 定义函数的方式如下
proc usage {} {
puts stderr "usage: $::argv0 ip usrname password"
exit
}
if {$argc != } { usage }
#利用脚本传参数
set hostip [lindex $argv ]
set username [lindex $argv ]
set password [lindex $argv ]
set timeout
# 利用expect的spawn命令来代理执行命令
spawn scp -r ../../hadoop ${username}@${hostip}:~
#获取期望的输出
expect {
#如果输出是 要输入密码
#注意下面的大括号 不能换行写,必须用Java风格,而且与前面的“之间要有一个空格,我当时犯了这错误,程序执行的结果很奇怪却不报错。
"*assword:" {
send "$password\n"
#输入密码后期待spawn代理的命令结束
expect eof
}
#如果不需要输入密码,那也是一样期待命令结束
expect eof
}

对于步骤3、4已经没什么挑战性了,很快就完成了。

下面我把所有代码贴上来

  1. setHadoopOnce.sh 这个文件是脚本执行的起点

 #!/bin/bash
#修改密码
pw=
loginName=hadoop
master=master
slave=slave
slaveNum=
set timeout
> ../hadoop-1.2./conf/masters
> ../hadoop-1.2./conf/slaves
#update local file
while read line
do
echo $line
ip=`echo $line | cut -d" " -f1`
name=`echo $line | cut -d" " -f2`
if [ ! -z $ip ]; then
echo $name
if [[ $name == maste* ]]; then
echo "$name" >> ../hadoop-1.2./conf/masters
elif [[ $name == slave* ]]; then
echo "$name" >> ../hadoop-1.2./conf/slaves
fi
fi
done < hosts
#upload file to all nodes
while read line
do
ip=`echo $line | cut -d" " -f1`
name=`echo $line | cut -d" " -f2`
if [ ! -z $ip ]; then
expect copyDataToAll.exp $ip $loginName $pw
expect setForAll.exp $ip $loginName $pw
fi
done < hosts while read line
do
ip=`echo $line | cut -d" " -f1`
name=`echo $line | cut -d" " -f2`
if [ ! -z $ip ]; then
if [[ $name == maste* ]]; then
expect setForMaster.exp $ip $loginName $pw
fi
fi
done < hosts

  2. copyDataToAll.exp 这个在setHadoopOnce.sh中的32行被调用,以复制文件到所有节点。

 #!/usr/bin/expect
proc usage {} {
puts stderr "usage: $::argv0 ip usrname password"
exit
}
if {$argc != } { usage }
set hostip [lindex $argv ]
set username [lindex $argv ]
set password [lindex $argv ]
set timeout
spawn scp -r ../../hadoop ${username}@${hostip}:~
expect {
"*assword:" {
send "$password\n"
expect eof
}
expect eof
}

  3. setForAll.exp 为所有节点进行一些配置工作,在setHadoopOnce.sh中的33行被调用.

#!/usr/bin/expect
proc usage {} {
puts stderr "usage: $::argv0 ip usrname password"
exit
}
proc connect {pwd} {
expect {
"*(yes/no)?" {
send "yes\n"
expect "*assword:" {
send "$pwd\n"
expect {
"*Last login:*" {
return
}
}
}
}
"*assword:" {
send "$pwd\n"
expect {
"*Last login:*" {
return
}
}
}
"*Last login:*" {
return
}
}
return
}
if {$argc != } { usage }
set hostip [lindex $argv ]
set username [lindex $argv ]
set password [lindex $argv ]
set timeout spawn ssh ${username}@${hostip}
if {[connect $password]} {
exit
}
#set host
send "sudo bash ~/hadoop/setup/addHosts.sh\r"
expect "*assword*"
send "$password\r"
expect "*ddhostsucces*"
sleep send "ssh-agent bash ~/hadoop/setup/sshGen.sh\n"
expect {
"*(yes/no)?" {
send "yes\n"
exp_continue
}
"*verwrite (y/n)?" {
send "n\n"
exp_continue
}
"*nter file in which to save the key*" {
send "\n"
exp_continue
}
"*nter passphrase*" {
send "\n"
exp_continue
}
"*nter same passphrase again*" {
send "\n"
exp_continue
}
"*our public key has been saved*" {
exp_continue
}
"*etsshGenSucces*" {
sleep
}
} send "bash ~/hadoop/setup/setEnvironment.sh\n"
expect "*etEnvironmentSucces*"
sleep send "exit\n"
expect eof

  3.1  addHosts.sh 在setForAll.exp中被调用,用于设置节点的hosts文件

#!/bin/bash

hadoopRoot=~/hadoop
hadoopPath=$hadoopRoot/hadoop-1.2.
setupPath=$hadoopRoot/setup
localip="`ifconfig |head -n 2|tail -n1 |cut -f2 -d: |cut -f1 -d" " `"
hostline="`grep "$localip$" $hadoopRoot/setup/hosts`"
sed -i /$hostline/\d $hadoopRoot/setup/hosts
#cp /etc/hosts /etc/hosts.hadoop.bak
for delip in `cat $hadoopRoot/setup/hosts`
do
delipline="`grep -n "$delip[[:space:]]" /etc/hosts |cut -f1 -d:`"
#echo $delipline
if [ -n "$delipline" ]; then
sed -i $delipline\d /etc/hosts
sleep 1s
#else
#echo "Your List have no the ip $delip"
fi
done
cat $hadoopRoot/setup/hosts >> /etc/hosts
rm -f "$setupPath"/sed*
echo "addhostsuccess"

  3.2 sshGen.sh 在setForAll.sh中被调用,用于生成sshkey。

#!/bin/bash
sshPath=~/.ssh
setupPath=~/hadoop/setup
rm "$sshPath"/authorized_keys
sleep
ssh-keygen -t rsa
cat "$sshPath"/id_rsa.pub >> "$sshPath"/authorized_keys
ssh-add
echo "setsshGenSuccess"

  3.3 setEnvironment.sh 在setForAll.sh中被调用,用于设置环境变量

#!/bin/bash
hadoopRoot=~/hadoop
hadoopPath=$hadoopRoot/hadoop-1.2.
setupPath=$hadoopRoot/setup
JAVA_VERSION=`java -version >& | awk '/java version/ {print $3}'|sed 's/"//g'|awk '{if ($1>=1.6) print "ok"}'` if [ "$JAVA_VERSION"x != "okx" ]; then
cat "$setupPath"/jdkenv >> ~/.bashrc
sleep
source ~/.bashrc
sleep
fi Hadoop_Version=`hadoop version|awk '/Hadoop/ {print $2}'|awk '{if ($1>=1.0) print "ok"}'` if [ "$Hadoop_Version"x != "okx" ]; then
cat "$setupPath"/hadoopenv >> ~/.bashrc
sleep
source ~/.bashrc
sleep
fi echo "setEnvironmentSuccess"

4. setForMaster.exp 远程ssh调用setForMaster.sh,以配置无密码登录的功能。

#!/usr/bin/expect
proc usage {} {
puts stderr "usage: $::argv0 ip usrname password"
exit
}
proc connect {pwd} {
expect {
"*(yes/no)?" {
send "yes\n"
expect "*assword:" {
send "$pwd\n"
expect {
"*Last login:*" {
return
}
}
}
}
"*assword:" {
send "$pwd\n"
expect {
"*Last login:*" {
return
}
}
}
"*Last login:*" {
return
}
}
return
} if {$argc != } { usage }
set hostip [lindex $argv ]
set username [lindex $argv ]
set password [lindex $argv ]
set timeout
spawn ssh ${username}@${hostip}
if {[connect $password]} {
exit
} send "ssh-agent bash ~/hadoop/setup/setForMaster.sh\n"
expect {
"*etForMasterSucces*" {
sleep
send "exit\n"
}
"*assword*" {
send "$password\n"
exp_continue
}
"*(yes/no)?" {
send "yes\n"
exp_continue
}
}

  4.1 setForMaster.sh

#!/bin/bash
while read line
do
ip=`echo $line | cut -d" " -f1`
name=`echo $line | cut -d" " -f2`
if [ ! -z $ip ]; then
if [[ $name == slave* ]]; then
scp $ip:~/.ssh/authorized_keys ~/tmpkey
cat ~/tmpkey >> ~/.ssh/authorized_keys
fi
fi
done < ~/hadoop/setup/hosts sleep rm -f ~/tmpkey
while read line
do
ip=`echo $line | cut -d" " -f1`
name=`echo $line | cut -d" " -f2`
if [ ! -z $ip ]; then
if [[ $name == slave* ]]; then
scp ~/.ssh/authorized_keys $ip:~/.ssh/authorized_keys
fi
fi
done < ~/hadoop/setup/hosts echo "setForMasterSuccess"

安装包打包下载地址: http://pan.baidu.com/s/1dDj6LHJ

hadoop自动安装的脚本与步骤的更多相关文章

  1. hadoop自动安装脚本

    还不能实现完全自动安装,只能算半自动的. 进行交互主要障碍有两点: 1. ssh-keygen的时候需要点击回车. 2. passwd 需要设置密码  如果谁能解决以上两点,欢迎email给我. 另外 ...

  2. 实用脚本----Linux下Jdk和Tomcat自动安装shell脚本总结

    系统环境为:ubuntu 14.04 一.JDK 自动安装脚本 jdk自动安装bash shell脚本,截止今天(2014/10/15)亲测可用: sudo su #切换到root权限 mkdir / ...

  3. pgsql自动安装shell脚本整理

    前面不断在vm虚拟机上测试pgsql,发觉安装还是有些麻烦的. 所以就收集了一些 1,http://www.davidghedini.com/pg/entry/postgresql_9_5_scrip ...

  4. 自动安装zabbix_agent脚本 -- python2

    #!/usr/bin/env python # -*- coding: utf-8 -*- import os ZABBIX_SERVER_IP='10.171.100.28' if os.path. ...

  5. Linux通用KVM自动安装Shell脚本(兼容所有Linux发行版/CentOS/Ubuntu)

    官网: https://github.com/retspen/webvirtmgr/wiki/Setup-Host-Server 安装: wget -O - https://retspen.githu ...

  6. centos自动安装镜像脚本

    #!/bin/bash ######################################################################################## ...

  7. 可以自动安装mysql数据库的一个shell脚本

    发布:thatboy   来源:脚本学堂     [大 中 小] 分享一例shell脚本,可以实现mysql数据库的自动安装,脚本写的不错,无论是用来学习,还是生产环境中应用,都是不错的,有需要的朋友 ...

  8. Linux学习之源码包安装与脚本安装(十八)

    Linux学习之源码包安装与脚本安装 目录 源码包与RPM包的区别 源码包安装 脚本安装 源码包与RPM包的区别 1.区别 安装之前的区别:概念上的区别 安装之后的区别:安装位置不同 源码包: 开源的 ...

  9. RHEL自动安装zookeeper的shell脚本

    RHEL自动安装zookeeper的shell脚本 A:本脚本运行的机器,Linux RHEL6 B,C,D,...:待安装zookeeper cluster的机器, Linux RHEL6 首先在脚 ...

随机推荐

  1. 源自梦想 自定义ViewGroup的整理_1

    今天说说自定义控件,稍微偏底层一点的东西.今天的主要任务是自己完全写代码,写一个ViewGroup,实现一个类似ViewPager这样的一个功能. 大家自定义View肯定写过,不过估计写的也不多.等大 ...

  2. jQuery的deferred对象详解(一)

    最近一段时间,都在研究jquery里面的$.Deffered对象,几天都搞不明白,其中源码的运行机制,网上查找了相关的资料,<jQuery的deferred对象详解>阮一峰老师的文章,里面 ...

  3. Google IP 最新地址

    原文地址:https://ideas.spkcn.com/technology/250.html 2015年 目前最新可以直接访问google的IP91.213.30.152173.194.77.14 ...

  4. CentOS服务器的16个监控命令

    你可以通过图形化用户界面(GUI)程序来获取这些外壳命令提供的大量信息,具体取决于使用哪一种Linux发行版.比如说,SUSE Linux就有一款出色的.图形化配置和管理工具YaST,KDE的KDE ...

  5. 常用的Linux系统调用命令

    常用的Linux系统调用命令   下面一些函数已经过时,被新的更好的函数所代替了(gcc在链接这些函数时会发出警告),但因为兼容的原因还保留着,这些函数将在前面标上“*”号以示区别.   一.进程控制 ...

  6. 第三回 Bootstrap3.x 起步

    基本模版 <!DOCTYPE html> <html lang="zh-cn"> <head> <meta charset="u ...

  7. static和public

    static:静态.   可以设置:静态类.静态变量.静态方法.   没有使用static修饰的成员为实例成员. 静态成员的使用:通过类名.   1.不加static修饰的成员是对象成员,归每个对象所 ...

  8. iOS-RunLoop,为手机省电,节省CPU资源,程序离不开的机制

    RunLoop是什么?基本操作是什么? 1.RunLoop的作用 RunLoop可以: 保持程序的持续运行 处理App中的各种事件(比如触摸事件.定时器事件.Selector事件) 节省CPU资源,提 ...

  9. OpenStack 加入新的节点,创建虚拟机失败的问题

    最开始做OpenStack的时候,由于只是为了部署测试用,因此将所有的部分都装在一台单网卡的机器上,费了九牛二虎之力终于部署成功,其中最主要的两块问题出现在以下两个方面: 1:nova.neutron ...

  10. 20150309—bs的保存状态

    http:保存状态方式,传值方式 session:(会话) 默认过期时间20分钟(20分内无任何操作自动销毁),针对用户独立,一般用来存储少量信息的 存值:session[“name”]=data;( ...