start-all.sh腳本現在已經廢棄,推薦使用start-dfs.sh和start-yarn.sh分別啟動HDFS和YARN。
在新一代的Hadoop里面HDFS稱為了統一存儲的平台,而YARN成為了統一計算的平台。
(1)調用start-dfs.sh啟動HDFS。之后JPS會出現NameNode,DataNode,SecondaryNameNode
(2)調用start-yarn.sh啟動YARN。之后JPS會出現ResourceManager,NodeManager
對於每個start腳本首先甚至啟動過程中用到的所有腳本,首先都是調用libexec/hadoop-config.sh配置相關環境變量
hadoop-config.sh
設置各種環境變量,包括:
HADOOP_PREFIX 整個Hadoop的安裝目錄
HADOOP_CONF_DIR 配置文件的目錄,一般是Hadoop安裝目錄下的etc/hadoop/
JAVA_HOME 從操作系統環境變量獲取,但是在SSH登陸到slave節點可能會出現問題,所以推薦在hadoop-env.sh中也設置一下。
JAVA_HEAP_MAX 啟動每個JVM默認的堆大小,目前是-Xmx1000m
CLASSPATH 找Jar包的地方,一般情況下Jar包存在Hadoop安裝目錄下的share/hadoop/目錄下的common,hdfs,httpfs,mapreduce,tools幾個子目錄下
HADOOP_LOG_DIR 就是存放日志的地方,默認是Hadoop安裝目錄下的logs目錄,這個很重要,運行中出了問題都是要通過log定位的。
NameNode,DataNode,SecondNameNode,ResourceManager,NodeManager的日志默認都在這個目錄下。
不過要注意默認的container的log是在/tmp/logs目錄下,害得我找container的log找了很長時間也沒找到。
HADOOP_LOGFILE
HADOOP_POLICYFILE
JAVA_LIBRARY_PATH Java運行時需要通過JNI調用native lib的環境變量。因為在Hadoop代碼中與操作系統緊密相關的一些操作和一些壓縮算法是有通過C編寫的native的系統實現的。就是libhadoop.so和libhdfs.so這樣的系統庫,通常放在Hadoop安裝目錄下的lib/native/里面。
HADOOP_OPTS 這個是啟動每個JVM時傳遞過去的參數
HADOOP_COMMON_HOME
HADOOP_HDFS_HOME
YARN_HOME
HADOOP_MAPRED_HOME
這些環境變量是運行Hadoop和YARN程序的環境變量,和我們把Hadoop安裝在哪個目錄下有關系。
start-dfs.sh
(1)執行hdfs-config.sh設置HDFS專有的環境變量。但是目前貌似沒有HDFS專有的環境變量,在這個文件里再次執行了下hadoop-config.sh
(2)啟動參數:upgrade,rollback還是正常啟動。
(3)然后就是分別調用對應的腳本啟動對應的模塊
NameNode
DataNode
SecondaryNameNode
ZooKeeper Failover
每個模塊都是調用hadoop-daemos.sh啟動的。
hadoop-daemons.sh和hadoop-daemon.sh的區別是:前者啟動多台機器上的daemon,后者負責在一台機器上啟動daemon,前者調用后者。連接這兩着的橋梁就是sbin/slave.sh,就是通過ssh登陸到slave機器上,然后在每台slave機器上執行hadoop-daemon.sh。
首先看看hadoop-daemons.sh
這個腳本的參數類似這樣:
|
1
|
--config
/home/orange/hadoop-2
.0.0-alpha
/etc/hadoop
--hostnames localhost --script
/home/orange/hadoop-2
.0.0-alpha
/sbin/hdfs
start namenode
|
因為上面這個例子是啟動NameNode,所以帶了–hostnames參數,用於指明分別到哪台機器上去運行hadoop-daemon.sh去啟動namenode。如果是啟動DataNode則不需要這個參數,因為如果不設定這個參數,會通過讀取etc/hadoop/slaves文件獲取slaves機器信息。
這個腳本的最后有個非常長的命令:
|
1
|
exec
"$bin/slaves.sh"
--config $HADOOP_CONF_DIR
cd
"$HADOOP_PREFIX"
\;
"$bin/hadoop-daemon.sh"
--config $HADOOP_CONF_DIR
"$@"
|
這個命令表示:在本shell內執行slaves.sh腳本,參數是后面那么一堆東西。
我們去slave.sh那打印出它接收到的參數看看:
|
1
|
--config
/home/orange/hadoop-2
.0.0-alpha
/etc/hadoop
cd
/home/orange/hadoop-2
.0.0-alpha ;
/home/orange/hadoop-2
.0.0-alpha
/sbin/hadoop-daemon
.sh --config
/home/orange/hadoop-2
.0.0-alpha
/etc/hadoop
--script
/home/orange/hadoop-2
.0.0-alpha
/sbin/hdfs
start namenode
|
在這個腳本里面通過ssh登陸到各個slave節點上,然后執行后面的cd進入slave節點的Hadoop安裝目錄,然后調用hadoop-daemon.sh去執行對應的操作。
hadoop-daemon.sh的參數是
|
1
|
localhost: --config
/home/orange/hadoop-2
.0.0-alpha
/etc/hadoop
--script
/home/orange/hadoop-2
.0.0-alpha
/sbin/hdfs
start namenode
|
執行hadoop-env.sh設置環境變量,因為即將啟動的JVM是由這個shell啟動的,所以這個環境變量會傳給JVM。
配置啟動單點NameNode或者DataNode的運行環境:除了hadoop-config.sh里面的以外還有HADOOP_LOG_DIR,HADOOP_PID_DIR,HADOOP_IDENT_STRING等,這些都是與運行這個daemon的本機相關的變量
最后通過
|
1
|
nohup
nice
-n $HADOOP_NICENESS $hdfsScript --config $HADOOP_CONF_DIR $
command
"$@"
>
"$log"
2>&1 <
/dev/null
&
|
啟動對應的進程,也就是hdfs start namenode命令。其實是調用 bin/hdfs腳本,啟動JVM。
hadoop-daemon.sh這個腳本是在每台機器上啟動各種JVM前的准備工作,包括設置環境變量什么的。因為每個腳本基本都會調用hadoop-config.sh,這個也不例外,所以我們理解一般情況下hadoop-config.sh里面的環境變量。但是從我的實際使用經驗來看,由於操作系統和SSH的問題,會導致SSH登陸到slave節點之后執行shell腳本的時候獲取系統環境變量失效的問題。例如,$JAVA_HOME環境變量,看hadoop-config.sh這個文件可知$JAVA_HOME直接從操作系統環境變量獲取。但是當hadoop-daemons.sh調用slaves.sh通過ssh登陸到各個slave節點之后去執行hadoop-daemon.sh時,在獲取$JAVA_HOME時出現失敗的情況。而如果在對應的那台機器上執行 echo $JAVA_HOME是沒有問題的。也就是SSH之后的環境變量獲取失敗。我的debian上就出現了這個問題,這個坑害死人。而在我的CentOS上卻沒有這樣的問題。通過搜索網絡得知是因為~/.bashrc不會被SSH調用,而~/.bash_profile或者~/.profile是會被SSH調用的。所以需要在~/.bash_profile或者~/.profile中通過類似下面的語句執行~/.bashrc
|
1
2
3
|
if
[ -f ~/.bashrc ];
then
. ~/.bashrc
fi
|
但是在我的debian上還是搞不定,至今原因未明。有對Debian熟悉的同學如果知道是什么原因可以Email我。
還好hadoop社區為了防止類似的問題,也做了很嚴謹的策略。在SSH登陸到每台slave之后,都會去調用hadoop-env.sh。這個文件很重要啊。我在看別人的攻略時,看別人在說要在這個hadoop-env.sh文件里設置$JAVA_HOME,但是就在想,我的系統環境變量里已經設置了$JAVA_HOME,難道你一個應用程序的環境變量比我系統的還管用?所以就試了下這個hadoop-env.sh不設置$JAVA_HOME,結果就出現了上面所說的問題。看來hadoop-env.sh正如其名,有關Hadoop的環境變量應該設置在這里,這樣才能在社么樣的底層系統環境下都能穩定運行。
start-yarn.sh
注意到這個腳本里不再執行hadoop-config.sh,而是執行yarn-config.sh。配置環境變量。(實際上yarn-config.sh還是會調用hadoop-config.sh的)
|
1
|
"$bin"
/yarn-daemon
.sh --config $YARN_CONF_DIR start resourcemanager
|
指定日志和pid的格式,也就是:yarn-orange-nodemanager-orange.log
yarn-orange-resourcemanager-orange.log
yarn-orange-nodemanager.pid
yarn-orange-resourcemanager.pid
通過執行下面這行代碼,啟動ResourceManager對應的JVM
|
1
|
nohup
nice
-n $YARN_NICENESS
"$YARN_HOME"
/bin/yarn
--config $YARN_CONF_DIR $
command
"$@"
>
"$log"
2>&1 <
/dev/null
&
|
|
1
|
"$bin"
/yarn-daemons
.sh --config $YARN_CONF_DIR start nodemanager
|
和啟動DataNode類似,也是通過SSH到每台slave節點上之后,執行yarn-daemon.sh啟動對應的NodeManager。
|
1
|
exec
"$bin/slaves.sh"
--config $YARN_CONF_DIR
cd
"$YARN_HOME"
\;
"$bin/yarn-daemon.sh"
--config $YARN_CONF_DIR
"$@"
|
注意這里面也存在和上面一樣的問題,所以推薦在yarn-env.sh里面也設置相關環境變量,要不然就會出現啟動Job的時候找不到類。。。
總的來說這個啟動過程分為多個層次,分別是:整個集群級別的配置,單台機器OS級別的配置,單個JVM級別的配置。
對那句話“
系統總是不可靠的,我們要通過軟件冗余來使得系統更加可靠”有了更深層次的認識。
