更新時(shí)間:2021-07-16 來源:黑馬程序員 瀏覽量:
服務(wù)器每天會產(chǎn)生大量日志數(shù)據(jù),并且日志文件可能存在于每個(gè)應(yīng)用程序指定的data目錄中,在不使用其它工具的情況下,將服務(wù)器中的日志文件規(guī)范的存放在HDFS中。通過編寫簡單的shell腳本,用于每天自動采集服務(wù)器上的日志文件,并將海量的日志上傳至HDFS中。由于文件上傳時(shí)會消耗大量的服務(wù)器資源,為了減輕服務(wù)器的壓力,可以避開高峰期,通常會在凌晨進(jìn)行上傳文件的操作。下面按照步驟實(shí)現(xiàn)Shell定時(shí)日志采集功能。
1.配置環(huán)境變量
首先在/export/data/logs目錄下(如果目錄不存在,則需要提前創(chuàng)建)使用vi命令創(chuàng)建upload2HDFS.sh腳本文件,在編寫Shell腳本時(shí),需要設(shè)置Java環(huán)境變量,即使我們當(dāng)前虛擬機(jī)節(jié)點(diǎn)已經(jīng)配置了Java環(huán)境變量,這樣做是用來提高系統(tǒng)的可靠性,保障運(yùn)行程序的機(jī)器在沒有配置環(huán)境變量的情況下依然能夠運(yùn)行腳本。代碼如下所示:
export JAVA_HOME=/export/servers/jdk export JRE_HOME=${JAVA_HOME}/jre export CLASSPATH=.:${JAVA_HOME}/lib:${JRE_HOME}/lib export PATH=${JAVA_HOME}/bin:$PATH
在配置完Java環(huán)境變量之后還需要配置Hadoop的環(huán)境變量,代碼如下所示:
export HADOOP_HOME=/export/servers/hadoop-2.7.4/ export PATH=${HADOOP_HOME}/bin:${HADOOP_HOME}/sbin:$PATH
2.準(zhǔn)備日志存放目錄和待上傳文件
為了讓開發(fā)者便于控制上傳文件的流程,可以在腳本中設(shè)置一個(gè)日志存放目錄和待上傳文件目錄,若上傳過程中發(fā)生錯(cuò)誤只需要查看該目錄就能知道文件的上傳進(jìn)度。添加相應(yīng)代碼如下所示:
#日志文件存放的目錄
log_src_dir=/export/data/logs/log/
#待上傳文件存放的目錄
log_toupload_dir=/export/data/logs/toupload/
為了保證后續(xù)腳本文件能夠正常執(zhí)行,還需要在啟動腳本前手動創(chuàng)建好這兩個(gè)目錄。
3.設(shè)置日志文件上傳的路徑
設(shè)置上傳的HDFS目標(biāo)路徑,命名格式以時(shí)間結(jié)尾,并且輸出打印信息。添加代碼如下所示:
#設(shè)置日期
date1=`date -d last-day +%Y_%m_%d`
#日志文件上傳到hdfs的根路徑
hdfs_root_dir=/data/clickLog/$date1/
#打印環(huán)境變量信息
echo "envs: hadoop_home: $HADOOP_HOME"
#讀取日志文件的目錄,判斷是否有需要上傳的文件
echo "log_src_dir:"$log_src_dir
4.實(shí)現(xiàn)文件上傳
上傳文件的過程就是遍歷文件目錄的過程,將文件首先移動到待上傳目錄,再從待上傳目錄中上傳到HDFS中。添加代碼如下所示:
ls $log_src_dir | while read fileName do if [[ "$fileName" == access.log.* ]]; then date=`date +%Y_%m_%d_%H_%M_%S \#將文件移動到待上傳目錄并重命名 echo "moving $log_src_dir$fileName to $log_toupload_dir"xxxxx_click_log_$fileName"$date" mv $log_src_dir$fileName $log_toupload_dir"xxxxx_click_log_$fileName"$date \#將待上傳的文件path寫入一個(gè)列表文件willDoing, echo $log_toupload_dir"xxxxx_click_log_$fileName"$date >> $log_toupload_dir"willDoing."$date fi done
最后將文件從待上傳目錄傳至HDFS中,具體代碼如下所示:
#找到列表文件willDoing ls $log_toupload_dir | grep will |grep -v "_COPY_" | grep -v "_DONE_" | while read line do \#打印信息 echo "toupload is in file:"$line \#將待上傳文件列表willDoing改名為willDoing_COPY_ mv $log_toupload_dir$line $log_toupload_dir$line"_COPY_" \#讀列表文件willDoing_COPY_的內(nèi)容(一個(gè)一個(gè)的待上傳文件名) \#此處的line 就是列表中的一個(gè)待上傳文件的path cat $log_toupload_dir$line"_COPY_" |while read line do \#打印信息 echo "puting...$line to hdfs path.....$hdfs_root_dir" hadoop fs -mkdir -p $hdfs_root_dir hadoop fs -put $line $hdfs_root_dir done mv $log_toupload_dir$line"_COPY_" $log_toupload_dir$line"_DONE_" done
如果在每天12點(diǎn)凌晨執(zhí)行一次,我們可以使用Linux Crontab表達(dá)式執(zhí)行定時(shí)任務(wù)。
0 0 * * * /shell/upload2HDFS.sh
上述crontab表達(dá)式是由6個(gè)參數(shù)決定,分別為分、時(shí)、日、月、周、命令組成,其中/shell/upload2HDFS.sh為shell腳本的絕對路徑。由于crontab表達(dá)式并非本書重點(diǎn),若想要深入學(xué)習(xí)的讀者可以自行查閱資料學(xué)習(xí)。
5.執(zhí)行程序展示運(yùn)行結(jié)果
一般日志文件產(chǎn)生是由業(yè)務(wù)決定,例如每小時(shí)滾動一次或者日志文件大小達(dá)到1G時(shí),就滾動一次,產(chǎn)生新的日志文件。為了避免每個(gè)日志文件過大導(dǎo)致上傳效率低,可以采取在滾動后的文件名后添加一個(gè)標(biāo)識的策略,例如access.log.x,x就是文件標(biāo)識,它可以為序號、日期等自定義名稱,該標(biāo)識用于表示日志文件滾動過一次,滾動后的文件,新產(chǎn)生的數(shù)據(jù)將不再寫入該文件中,當(dāng)滿足業(yè)務(wù)需求時(shí),則文件可以被移動到待上傳目錄,如圖1所示。
圖1 滾動日志文件
從圖1可以看出,為了模擬生產(chǎn)環(huán)境,在日志存放目錄/export/data/logs/log/中,手動創(chuàng)建日志文件,access.log表示正在源源不斷的產(chǎn)生日志的文件,access.log.1、access.log.2等表示已經(jīng)滾動完畢的日志文件,即為待上傳日志文件。
在upload2HDFS.sh文件路徑下使用“sh upload2HDFS.sh”指令執(zhí)行程序腳本,打印執(zhí)行流程,如圖2所示。
圖2 運(yùn)行腳本
從圖2可以看出,首先將日志存放目錄log中的日志文件移動到待上傳toupload目錄下,并根據(jù)業(yè)務(wù)需求重命名,然后腳本自動執(zhí)行“hadoop put”上傳命令,將待上傳目錄下的所有日志文件上傳至HDFS中。通過HDFS Web界面可以看到,需要采集的日志文件已經(jīng)按照日期分類,上傳到HDFS中,如圖3所示。
圖3 日志采集文件
小提示:
Shell腳本語言并本章節(jié)的重點(diǎn),讀者只需要掌握本節(jié)案例的業(yè)務(wù)和思想,以及可以讀懂簡單的Shell腳本語言即可。