2014年3月29日 星期六

利用inotify + rsync 實現Linux文件即時同步

一、檔案控管機制-Inotify
inotify可以幫助你即時的觀測檔案的改變,並回送通知給你,inotify把檔案狀態的變化分為以下

IN_ACCESS,即檔案被存取 
IN_MODIFY
,文件被 write 
IN_ATTRIB
,檔案屬性被修改,如 chmodchowntouch  
IN_CLOSE_WRITE
,可寫文件被 close 
IN_CLOSE_NOWRITE
,不可寫文件被 close 
IN_OPEN
,文件被 open 
IN_MOVED_FROM
,文件被移走, mv 
IN_MOVED_TO
,文件被移來,如 mvcp 
IN_CREATE
,創建新文件 
IN_DELETE
,檔被刪除,如 rm 
IN_DELETE_SELF
,自刪除,即一個可執行檔在執行時刪除自己 
IN_MOVE_SELF
,自移動,即一個可執行檔在執行時移動自己 
IN_UNMOUNT
,宿主檔案系統被 umount 
IN_CLOSE
,文件被關閉,等同於(IN_CLOSE_WRITE | IN_CLOSE_NOWRITE) 
IN_MOVE
,文件被移動,等同於(IN_MOVED_FROM | IN_MOVED_TO) 

首先查看系統是否支持inotify,看看是否有 /proc/sys/fs/inotify/目錄,以確定內核是否支援inotify
#ls /proc/sys/fs/inotify/

二、安裝rsync inotify-tools
#yum install rsync
#wget http://github.com/downloads/rvoicilas/inotify-tools/inotify-tools-3.14.tar.gz
#tar zxvf inotify-tools-3.14.tar.gz
#./configure --prefix=/xxx/xxx
#make
#make install

如果執行inotifywait時,提示缺少libinotifytools.so.0,請將libinotifytools.so.0複製到/lib下即可


三、撰寫即時同步script及測試
測試環境為即時監控172.16.2.8/home/jacky目錄並同步至172.16.2.49:/home

先讓ssh登入免密碼,在172.16.2.8
#ssh-copy-id  -i ~/.ssh/id_rsa.pub root@172.16.2.49

然後將以下紅色代碼存成script
###############################################################
#!/bin/bash
src=/home/jacky
ip=172.16.2.49
des=/home/

/usr/local/bin/inotifywait -mrq --timefmt '%d/%m/%y %H:%M' --format  '%T %w%f' \
 -e modify,delete,create,attrib ${src} \
| while read  file
        do
                rsync -avz --delete --progress ${src} root@${ip}:${des} &&
                echo "${file} was rsynced"
                echo "---------------------------------------------------------------------------"
        done
#################################################################

script運行後,來源172.16.2.8:/home/jacky內檔案有任何變動即會同步172.16.2.49:/home/

/usr/local/bin/inotifywait -mrq --timefmt '%d/%m/%y %H:%M' --format  '%T %w%f' \
 -e modify,delete,create,attrib ${src} \

該段指令返回值類似於:
10/09/12 19:15 /home/jacky/xxx
三個返回值會做為參數傳給read,觸發rsync指令


rsync 參數說明
-a, --archive 歸檔模式,表示以遞迴方式傳輸檔,並保持所有檔案屬性
-v, --verbose 詳細模式輸出 
-z, --compress 對備份的檔在傳輸時進行壓縮處理 
--delete 刪除那些DSTSRC沒有的檔
--progress 在傳輸時顯示傳輸過程 

inotifywait 相關參數可用man查看


Hadoop 1.1.2 安裝實作

未命名 1
Hadoop 1.1.2 安裝
<![if !supportLists]> 一、  <![endif]> Hadoop安裝前置作業
<![if !supportLists]> 1.       <![endif]> Linux平台上安裝JAVAsshd 服務,官方建議JAVA使用Sun 1.6.x版本,這邊測試使用為JDK 1.6.41版本,
建議先將iptables關閉,方便測試。
<![if !supportLists]> 2.       <![endif]> 由於目前1.1.2為穩定版本,下載Hadoop 1.1.2.tar.gz 原始檔,官方下載點如下
#tar zxvf hadoop-1.1.2.tar.gz
#mv hadoop-1.1.2 /home/hadoop
<![if !supportLists]> 3.       <![endif]> 解壓 hadoop 1.1.2.tar.gz並放至目錄/home/hadoop,編輯conf/hadoop-env.sh,在裡面定義JAVA_HOME的目錄位置
#vi conf/hadoop-env.sh
#export JAVA_HOME=/usr/java/jdk1.6.0_41/
<![if !supportLists]> 二、  <![endif]> Hadoop單機模式-預設的Hadoop模式,不用修改任何設定檔,常用來Debug
在單機模式下利用Hadoopgrep範例
#cd /home/hadoop
#mkdir input
#cp conf/*.xml input
# bin/hadoop jar hadoop-examples-*.jar grep input output 'dfs[a-z.]+' 
#cat output/*
<![if !supportLists]> 三、  <![endif]> 偽分散式檔案系統模式-單節點的運行模式
修改conf/core-site.xml
<configuration>
     <property>
         <name>fs.default.name</name>
         <value>hdfs://localhost:9000</value>
     </property>
</configuration>
 
修改conf/hdfs-site.xml:
<configuration>
     <property>
         <name>dfs.replication</name>
         <value>1</value>
     </property>
</configuration>
 
修改conf/mapred-site.xml:
<configuration>
     <property>
         <name>mapred.job.tracker</name>
         <value>localhost:9001</value>
     </property>
</configuration>                          
設定ssh登入本機免密碼,並測試
#ssh-keygen -t dsa -P '' -f ~/.ssh/id_dsa
#cat ~/.ssh/id_dsa.pub >> ~/.ssh/authorized_keys
#ssh localhost
格式化分散式檔案系統
#bin/hadoop namenode –format
執行Hadoop 服務
#bin/start-all.sh
開啟Hadoop網頁管理
先將本機檔案放至分散式檔案系統,利用分散式檔案系統測試grep範例
# bin/hadoop fs –put conf input
#bin/hadoop jar hadoop-examples-*.jar grep input output 'dfs[a-z.]+'
將分散式檔案系統的結果傳至本機查看
#bin/hadoop fs –get output output
#cat output/*
或直接在分散式檔案系統查看結果
#bin/hadoop fs –cat output/*
 
<![if !supportLists]> 四、  <![endif]> 分散式檔案系統模式
修改/etc/hosts,並新增Hadoop節點
#vi /etc/hosts
172.16.2.201    HadoopMaster
172.16.2.202    HadoopSlave1
172.16.2.203    HadoopSlave2
172.16.2.204    HadoopSlave3
172.16.2.205    HadoopSlave4
設定Master ssh登入SlaveSlave登入Master雙向免密碼
Master主機上生成ssh key
#ssh-keygen -t dsa -P '' -f ~/.ssh/id_dsa
#cat ~/.ssh/id_dsa.pub >> ~/.ssh/authorized_keys
key複製到各台Slave主機
#scp /root/.ssh/* 172.16.2.202:/root/.ssh/
#scp /root/.ssh/* 172.16.2.203:/root/.ssh/
#scp /root/.ssh/* 172.16.2.204:/root/.ssh/
#scp /root/.ssh/* 172.16.2.205:/root/.ssh/
修改conf/core-site.xml
<configuration>
     <property>
         <name>fs.default.name</name>
         <value>hdfs://172.16.2.201:9000</value>
     </property>
</configuration>
修改conf/hdfs-site.xml:
<configuration>
     <property>
         <name>dfs.replication</name>
         <value>1</value>
     </property>
<property>
        <name>dfs.permissions</name>
        <value>false</value>
     </property>
</configuration>
dfs.replication為數據需要備份的數量,此數若大於集群機器數會出錯
dfs.permissions設定dfs檔案權限檢查,關閉可讓其他使用者運行hadoop
修改conf/mapred-site.xml:
<configuration>
     <property>
         <name>mapred.job.tracker</name>
         <value>172.16.2.201:9001</value>
     </property>
</configuration>                          
修改conf/masters,將localhost 改為
HadoopMaster
修改 conf/slaves,將localhost改為
HadoopSlave1
HadoopSlave2
HadoopSlave3
HadoopSlave4
Hadoop目錄複製到各Slaves
#scp –r /home/hadoop 172.16.2.202:/home/
#scp –r /home/hadoop 172.16.2.203:/home/
#scp –r /home/hadoop 172.16.2.204:/home/
#scp –r /home/hadoop 172.16.2.205:/home/
 
格式化分散式檔案系統
#bin/hadoop namenode –format
執行Hadoop 服務
#bin/start-all.sh
開啟Hadoop網頁管理
先將本機檔案放至分散式檔案系統,利用分散式檔案系統測試grep範例
# bin/hadoop fs –put conf input
#bin/hadoop jar hadoop-examples-*.jar grep input output 'dfs[a-z.]+'
將分散式檔案系統的結果傳至本機查看
#bin/hadoop fs –get output output
#cat output/*
或直接在分散式檔案系統查看結果
#bin/hadoop fs –cat output/*
 
 
Apache基金會規畫的Hadoop體系中還有許多武功高強的周邊專案,如可支援SQL語法的Hive,不懂Java也能撰寫MapReducePig,這些都是開發者不能錯過的Hadoop相關專案 

HDFSMapReduce只是打造Hadoop平臺最基本的核心套件,在Apache基金會的網站中還有其他的相關開源套件,共同組成了一個Hadoop體系(Hadoop Ecosystem)。 

透過這些相關專案的延伸,開發人員就算不懂Java,也可以用特定Script語言來撰寫Hadoop上的MapReduce程式,甚至可以用SQL語法來查詢HDFS上的資料。這些周邊專案可說是大幅強化Hadoop功能的軟體軍火庫,想要善用Hadoop的開發人員不可錯過。其中重要的周邊專案包括HBaseHive ZooKeeperPigMahout 

HBase 能容納PB資料量的分散式資料庫 
HBase
是專門用於Hadoop檔案系統上的資料庫系統,採取Column-Oriented 資料庫設計,不同於傳統的關聯式資料庫,例如沒有資料表、Schema資料架構等功能,而是採用Key-Value形式的資料架構,每筆資料都有一個Key值對應到一個Value值,再透過多維度的對應關係來建立類似表格效果的資料架構。如此就能採取分散式儲存方式,可以擴充到數千臺伺服器,以應付PB等級的資料處理。 

Hive 可用SQL語法存取Hadoop資料 
Hive
是建置在HDFS上的一套分散式資料倉儲系統,可讓使用者以慣用的SQL語法,來存取Hadoop檔案中的大型資料集,例如可以使用JoinGroup byOrder by等,而這個語法稱為Hive QL。不過,Hive QLSQL並非完全相同,例如Hive就不支援Store ProcedureTrigger等功能。 

Hive
會將使用者輸入的Hive QL指令編譯成Java程式,再來存取HDFS檔案系統上的資料,所以,執行效率依指令複雜度和處理的資料量而異,可能有數秒鐘,甚至是數分鐘的延遲。和HBase相比,Hive容易使用且彈性高,但執行速度較慢。不少資料庫系統,都是透過先連結到Hive,才能與Hadoop整合。例如微軟就是透過Hive ODBC驅動程式,將SQL指令轉換成Hive QL,讓Excel可以存取Hadoop上的資料。 

在同一個Hadoop叢集中,Hive可以存取HBase上的資料,將HBase上的資料對應成Hive內的一個表格。 

Pig 不懂Java開發也能寫MapReduce 
Pig
提供了一個Script語言Pig Latin,語法簡單,類似可讀性高的高階Basic語言,可用來撰寫MapReduce程式。Pig會自動將這些腳本程式轉換,成為能在Hadoop中執行的MapReduce Java程式。 

因此,使用者即使不懂Java也能撰寫出MapReduce。不過,一般來說,透過Pig腳本程式轉換,會比直接用Java撰寫MapReduce的效能降低了25%。 

ZooKeeper Hadoop內部伺服器能協同運作 
Zookeeper
是監控和協調Hadoop分散式運作的集中式服務,可提供各個伺服器的配置和運作狀態資訊,用於提供不同Hadoop系統角色之間的工作協調。 

HBase資料庫為例,其中有兩種伺服器角色:Region伺服器角色和Master伺服器角色,系統會自動透過ZooKeeper監看Master伺服器的狀態,一旦Master的運作資訊消失,代表當機或網路斷線,HBase就會選出另一臺Region伺服器成為Mater角色來負責管理工作。 

Mahout 立即可用的常用MapReduce函式庫 
Hadoop中,開發人員必須將資料處理作法拆解成可分散運算的MapReduce程式,因為思考邏輯和常見的程式開發邏輯不同,所以開發難度很高。Mahout則提供了一個常用的MapReduce函式庫,常見的數值分析方法、叢集分類和篩選方式,都已經有對應的MapReduce函數可呼叫,開發人員就不必再重複開發一次。
 

讓 Tomcat 獨立輸出各個 virtual host 的 catalina.out 檔案

以下測試環境為 RHEL5tomcat 6.0.39

一、swallowOutput設定

官網說明
If the value of this flag is true, the bytes output to System.out and System.err by the web application will be redirected to the web application logger. If not specified, the default value of the flag is false.

設定 tomcat/conf/context.cml
<Context swallowOutput="true">
……………………………………
</Context>

二、第一種方法,設定 log4j
1.      tomcat/lib/ 下建立 log4j.properties,以下為範例檔
##############################################################
#定義logger,名字這邊可自訂,第一個為輸出層級,為了讓log分開輸出,這邊只定義輸出層級
log4j.rootLogger=INFO, CATALINA
#定義每個appender的路徑與作用,名稱為剛定義的logger,參數請參考log4j官方文件
log4j.appender.CATALINA=org.apache.log4j.FileAppender
log4j.appender.CATALINA.File=${catalina.base}/logs/catalina.out
log4j.appender.CATALINA.Append=true
log4j.appender.CATALINA.Encoding=UTF-8
log4j.appender.CATALINA.layout = org.apache.log4j.PatternLayout
log4j.appender.CATALINA.layout.ConversionPattern = %d [%t] %-5p %c- %m%n

log4j.appender.S=org.apache.log4j.FileAppender
log4j.appender.S.File=${catalina.base}/logs/webapps1.out
log4j.appender.S.Append=true
log4j.appender.S.Encoding=UTF-8
log4j.appender.S.layout = org.apache.log4j.PatternLayout
log4j.appender.S.layout.ConversionPattern = %d [%t] %-5p %c- %m%n

log4j.appender.R=org.apache.log4j.FileAppender
log4j.appender.R.File=${catalina.base}/logs/webapps2.out
log4j.appender.R.Append=true
log4j.appender.R.Encoding=UTF-8
log4j.appender.R.layout = org.apache.log4j.PatternLayout
log4j.appender.R.layout.ConversionPattern = %d [%t] %-5p %c- %m%n

log4j.logger.org.apache.catalina.core.ContainerBase.[Catalina].[localhost]=INFO, S
log4j.logger.org.apache.catalina.core.ContainerBase.[Catalina].[jacky.com]=INFO, R
#設定tocmat host綁定logger, hoststomcat server.xml host名稱,
#這邊為 localhost綁定CATALINA logger名稱, jacky.com 綁定 R logger名稱
log4j.logger.org.apache.catalina.core.ContainerBase.[Catalina].[localhost]=INFO,S
log4j.logger.org.apache.catalina.core.ContainerBase.[Catalina].[jacky.com]=INFO,R
###################################################################

2.      下載 log4j ,將log4j-1.2.17.jar 放到 tomcat/lib/

3.      下載 tomcat-juli.jar  tomcat-juli-adapters.jar放到 tomcat/lib/

4.      設定全域log4j
將剛下載的tomcat-juli.jar 取代 tomcat/bin/tomcat-juli.jar
5.      刪除 tomcat/conf/logging.properties 避免內建java.util.logging 產生log
6.      啟動tomcat


三、第二種方法,利用tomcat 內建logging.properties
1. 修改 tomcat/conf/logging.properties
####################################################################
#建立handlers,前綴名可自訂,但前面一定是數字開頭,
handlers = 1catalina.org.apache.juli.FileHandler, 2localhost.org.apache.juli.FileHandler, 3jacky.org.apache.juli.FileHandler

.handlers = 1catalina.org.apache.juli.FileHandler

#設定每個handlers 層級與路徑
1catalina.org.apache.juli.FileHandler.level = FINE
1catalina.org.apache.juli.FileHandler.directory = ${catalina.base}/logs
1catalina.org.apache.juli.FileHandler.rotatable = false
1catalina.org.apache.juli.FileHandler.prefix = catalina
1catalina.org.apache.juli.FileHandler.suffix = .out

2localhost.org.apache.juli.FileHandler.level = FINE
2localhost.org.apache.juli.FileHandler.directory = ${catalina.base}/logs
2localhost.org.apache.juli.FileHandler.rotatable = false
2localhost.org.apache.juli.FileHandler.prefix = webapps1
2localhost.org.apache.juli.FileHandler.suffix = .out

3jacky.org.apache.juli.FileHandler.level = FINE
3jacky.org.apache.juli.FileHandler.directory = ${catalina.base}/logs
3jacky.org.apache.juli.FileHandler.rotatable = false
3jacky.org.apache.juli.FileHandler.prefix = webapps2
3jacky.org.apache.juli.FileHandler.suffix = .out


#綁定handler tomcat host
org.apache.catalina.core.ContainerBase.[Catalina].[localhost].level = INFO
org.apache.catalina.core.ContainerBase.[Catalina].[localhost].handlers = 2localhost.org.apache.juli.FileHandler
org.apache.catalina.core.ContainerBase.[Catalina].[jacky.com].level = INFO
org.apache.catalina.core.ContainerBase.[Catalina].[jacky.com].handlers = 3jacky.org.apache.juli.FileHandler
#############################################################################
2. tomcat啟動會讀tomcat/conf/logging.properties設定,如果檔案不可讀或未設定,則預設變為$JAVA_HOME/lib/logging.properties

3. tocmat 會 tomcat/bin/startup.sh 起動catalina.sh,所以java參數及變數要寫在tomcat/bin/catalina.sh,啟動才會生效