hadoop自動安裝的腳本與步驟


最近要在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.1/conf/masters elif [[ $name == slave* ]]; then echo "$name" >> ../hadoop-1.2.1/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 1 } if {$argc != 3} { usage } #利用腳本傳參數 set hostip [lindex $argv 0] set username [lindex $argv 1] set password [lindex $argv 2] set timeout 100000 # 利用expect的spawn命令來代理執行命令 spawn scp -r ../../hadoop ${username}@${hostip}:~ #獲取期望的輸出 expect { #如果輸出是 要輸入密碼
#注意下面的大括號 不能換行寫,必須用Java風格,而且與前面的“之間要有一個空格,我當時犯了這錯誤,程序執行的結果很奇怪卻不報錯。
"*assword:" { send "$password\n" #輸入密碼后期待spawn代理的命令結束 expect eof } #如果不需要輸入密碼,那也是一樣期待命令結束 expect eof }

 

對於步驟3、4已經沒什么挑戰性了,很快就完成了。

下面我把所有代碼貼上來

  1. setHadoopOnce.sh 這個文件是腳本執行的起點

 1 #!/bin/bash
 2 #修改密碼
 3 pw=123456
 4 loginName=hadoop
 5 master=master
 6 slave=slave
 7 slaveNum=1
 8 set timeout 100000
 9 > ../hadoop-1.2.1/conf/masters
10 > ../hadoop-1.2.1/conf/slaves
11 #update local file
12 while read line
13 do
14     echo $line
15     ip=`echo $line | cut -d" " -f1`
16     name=`echo $line | cut -d" " -f2`
17     if [ ! -z $ip ]; then
18         echo $name
19         if [[ $name == maste* ]]; then
20         echo "$name" >> ../hadoop-1.2.1/conf/masters
21         elif [[ $name == slave* ]]; then
22         echo "$name" >> ../hadoop-1.2.1/conf/slaves
23         fi
24     fi
25 done < hosts
26 #upload file to all nodes
27 while read line
28 do
29     ip=`echo $line | cut -d" " -f1`
30     name=`echo $line | cut -d" " -f2`
31     if [ ! -z $ip ]; then
32         expect copyDataToAll.exp $ip $loginName $pw
33         expect setForAll.exp $ip $loginName $pw
34     fi
35 done < hosts
36 
37 while read line
38 do
39     ip=`echo $line | cut -d" " -f1`
40     name=`echo $line | cut -d" " -f2`
41     if [ ! -z $ip ]; then
42         if [[ $name == maste* ]]; then
43             expect setForMaster.exp $ip $loginName $pw
44         fi
45     fi
46 done < hosts

  2. copyDataToAll.exp 這個在setHadoopOnce.sh中的32行被調用,以復制文件到所有節點。

 1 #!/usr/bin/expect
 2 proc usage {} {
 3     puts stderr "usage: $::argv0 ip usrname password"
 4     exit 1
 5 }
 6 if {$argc != 3} { usage }
 7 set hostip [lindex $argv 0]
 8 set username [lindex $argv 1]
 9 set password [lindex $argv 2]
10 set timeout 100000
11 spawn scp -r ../../hadoop ${username}@${hostip}:~
12 expect {
13     "*assword:" {
14         send "$password\n"
15         expect eof
16     }
17     expect eof
18 }

  3. setForAll.exp 為所有節點進行一些配置工作,在setHadoopOnce.sh中的33行被調用.

#!/usr/bin/expect
proc usage {} {
    puts stderr "usage: $::argv0 ip usrname password"
    exit 1
}
proc connect {pwd} {
    expect {
        "*(yes/no)?" {
            send "yes\n"
            expect "*assword:" {
                send "$pwd\n"
                expect {
                    "*Last login:*" {
                        return 0
                    }
                }
            }
        }
        "*assword:" {
            send "$pwd\n"
            expect {
                "*Last login:*" {
                    return 0
                }
            }
        }
        "*Last login:*" {
            return 0
        }
    }
    return 1
}
if {$argc != 3} { usage }
set hostip [lindex $argv 0]
set username [lindex $argv 1]
set password [lindex $argv 2]
set timeout 100000

spawn ssh ${username}@${hostip}
if {[connect $password]} {
    exit 1
}
#set host
send "sudo bash ~/hadoop/setup/addHosts.sh\r"
expect "*assword*"
send "$password\r"
expect "*ddhostsucces*"
sleep 1

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 1
    }
}

send "bash ~/hadoop/setup/setEnvironment.sh\n"
expect "*etEnvironmentSucces*"
sleep 1

send "exit\n"
expect eof

  3.1  addHosts.sh 在setForAll.exp中被調用,用於設置節點的hosts文件

#!/bin/bash

hadoopRoot=~/hadoop
hadoopPath=$hadoopRoot/hadoop-1.2.1
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 1
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.1
setupPath=$hadoopRoot/setup
JAVA_VERSION=`java -version 2>&1 | 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 1
    source ~/.bashrc
    sleep 1
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 1
    source ~/.bashrc
    sleep 1
fi

echo "setEnvironmentSuccess"

4. setForMaster.exp 遠程ssh調用setForMaster.sh,以配置無密碼登錄的功能。

#!/usr/bin/expect
proc usage {} {
    puts stderr "usage: $::argv0 ip usrname password"
    exit 1
}
proc connect {pwd} {
    expect {
        "*(yes/no)?" {
            send "yes\n"
            expect "*assword:" {
                send "$pwd\n"
                expect {
                    "*Last login:*" {
                        return 0
                    }
                }
            }
        }
        "*assword:" {
            send "$pwd\n"
            expect {
                "*Last login:*" {
                    return 0
                }
            }
        }
        "*Last login:*" {
            return 0
        }
    }
    return 1
}

if {$argc != 3} { usage }
set hostip [lindex $argv 0]
set username [lindex $argv 1]
set password [lindex $argv 2]
set timeout 100000
spawn ssh ${username}@${hostip}
if {[connect $password]} {
    exit 1
}

send "ssh-agent bash ~/hadoop/setup/setForMaster.sh\n"
expect {
    "*etForMasterSucces*" {
        sleep 1
        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 1

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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM