shell腳本監控文件夾文件實現自動上傳數據到hive表

 

1、輸入字段,建hive表腳本 createtb.sh

#!/bin/bash
echo "---------createtb.sh--------------"
#string="tablename;field1,field2,field3,field4,field5,field6,field7;partition1,partition2"
string=$*
group=(${string//;/ })
for i in ${group[@]};do
    ((m++))
    if [[ m -eq 1 ]];then
        tables=$i
    elif [[ m -eq 2 ]];then
        fields=$i
    else partitions=$i
    fi
done
# echo "tables:" $tables
# echo "fileds:" $fields
# echo "partitions:" $partitions
# echo "-----------------"
field=(${fields//,/ })
partition=(${partitions//,/ })

# 創建表目錄
$(mkdir -p /home/hive/observation/$tables ; chmod 777 /home/hive/observation/$tables)

# 數據庫名稱,這裏不作爲參數用自變量寫了
database="observation"
# hive 拼接語句,分爲h1,h2,h3
# h1是建表語句的前半部,h2是參數列表中間部分,h3是建表語句的後半部
h1="create table $database.$tables"
# 在當前目錄下創建文本文件temp,如果文件存在則清空文件
$(> temp)
# for 循環將參數追加到當前目錄的temp文件,逗號分隔,echo -n 不換行
for i in ${field[@]};do
	echo -n $i" varchar(255)," >> temp
done
# h2取temp文本里的字符串
temp=$(cat temp)
# 將字符串最後的一個逗號去掉
h2="(${temp%*,})"
# 在當前目錄下創建文本文件tmp,如果文件存在則清空文件
$(> tmp)
# for 循環將參數追加到當前目錄的temp文件,逗號分隔,echo -n 不換行
for i in ${partition[@]};do
	echo -n $i" varchar(255)," >> tmp
done
# h3取temp文本里的字符串
tmp=$(cat tmp)
# 將字符串最後的一個逗號去掉
# h3是建表語句的後半部
h3="
partitioned by
(${tmp%*,})
row format delimited 
fields terminated by '\t'
lines terminated by '\n'
stored as textfile
location '/user/hive/warehouse/$database.db/$tables';
"
echo $h1$h2$h3
$(hive -e "$h1$h2$h3")
$(rm -rf tmp temp)

echo "-------create hive table successfully--------"

#/bin/bash /home/hive/loadtb.sh
#exec /home/hive/loadtb.sh
#source /home/hive/loadtb.sh
#fork /home/hive/loadtb.sh
# 第一個參數爲表名,第二個參數爲分區字段
#/home/hive/loadtb.sh $tables $partitions
/home/hive/monitor.sh $*

2、監控目錄腳本 monitor.sh

# -------------接收參數,解析字符串--------------
echo "---------monitor.sh--------------"
string=$*
group=(${string//;/ })
for i in ${group[@]};do
    ((m++))
    if [[ m -eq 1 ]];then
        tables=$i
    elif [[ m -eq 2 ]];then
        fields=$i
    else partitions=$i
    fi
done
tables=(${tables//;/ })
field=(${fields//,/ })
partition=(${partitions//,/ })
# -------------接收參數,解析字符串--------------


# 第一個參數爲表名,也是監控的文件夾名稱
tables=$tables
echo "tables:$tables"
echo "----------監控目錄----------"
# 獲取當前數據文件夾下的文件數量
let "total=$(ls /home/hive/observation/$tables | wc -l)"
echo "數據文件數量:$total"

# 如果文件爲空,則初始化log文件
if (( total==0 ));then
    # 初始化log文件,賦予10行默認時間值
    for (( i=0;i<10;i++ ));do
        $(echo "2020-01-01 00:00:00.00000000$i" >> /home/log/hive/observation/$tables.log)
    done
fi

# 獲取log文件中的最後一個日期
logdate=$(tail -n 1 /home/log/hive/observation/$tables.log)
echo "log 日誌最新日期:$logdate"

# 獲取數據目錄下的最新的日期
newdate=$(ls --full-time -lt /home/hive/observation/$tables | tail -n -$total | awk '{print $6,$7}' | head -n 1)
echo "數據目錄最新日期:$newdate"

# 將兩個時間轉爲時間戳
LOGDATE=`date -d "$logdate" +%s`
NEWDATE=`date -d "$newdate" +%s`
echo "log 日誌最新時間戳:$LOGDATE"
echo "數據目錄最新時間戳:$NEWDATE"

# 獲取數據目錄所有的日期信息
alldate=$(ls --full-time -lt /home/hive/observation/$tables | tail -n -$total | awk '{print $6,$7}')
echo "數據目錄所有日期信息:"
echo "$alldate"

# 數據目錄日期字符串長度
let len=${#alldate}
echo "數據目錄日期字符串長度:$len"

# 由於日期信息是空格連續的,單個日期也有空格,所有需要特殊處理
for((i=0;i<total;i++));do
    let start=i*30
    date[$i]=${alldate:$start:30}
done
echo "字符串切割後的日期信息:"
echo "${date[*]}"
((n=-1))
echo "--------開始遍歷數據目錄----------"
# for循環遍歷數組date
# 數組是從最新遍歷到最舊的
for((i=0;i<${#date[*]};i++));do
    # 每次遍歷得到數據日期時間戳
    TIMECR=`date -d "${date[$i]}" +%s`
    #echo $TIMECR
    # log日誌的最新數據如果和遍歷的數據相等
    if [[ $LOGDATE -eq $TIMECR ]];then
    #if {[ "$LTIME" = "${date[$i]}" ]];then
        #echo "$LTIME";echo ${date[$i]}
        #echo "$i,$LTIME,${date[$i]}"
        echo $i
        (( n=$i ))  #拿到第n行數據
        # echo "有相同日期信息,截取最新日期到之前的日期信息"
        # echo "${date[$i]}${date[0]}"
        # echo "需要加載的這幾行數據:$i"
    break
    fi
    #echo ${date[$i]}
done
echo "--------結束遍歷數據目錄----------"
echo "n=$n"
# echo "取最新數據的第:$n個"
# echo "最新數據是:${date[0]}"

# n=-1則表明日誌的最新日期裏邊沒有文件裏邊的日期
# 此情況則視爲所有數據都要加載到hive表裏邊
if (( n == -1 ));then
    echo "n == -1 , 第一次加載數據,所有數據加載到hive表,${date[0]},$newdate" >> /home/hive/n.log
    # 刪除log第一行數據
    $(sed -i '1d' /home/log/hive/observation/$tables.log)
    # 把之前讀取的最新日期數據加到log文件下
    echo -n "${date[0]}" >> /home/log/hive/observation/$tables.log   
    echo "" >> /home/log/hive/observation/$tables.log
    /home/hive/loadtb_all.sh $tables $partitions
# 如果n==0表示沒有最新數據(n=0爲最新的數據),既不需要處理
elif (( n == 0));then
    echo "n == 0 , 沒有最新數據,${date[0]} "
    echo "n == 0 , 沒有最新數據,${date[0]} " >> /home/hive/n.log
else 
    echo "最新數據是:${date[0]}"
    echo "最新數據是:${date[0]}" >> /home/hive/n.log
    # 刪除log第一行數據
    $(sed -i '1d' /home/log/hive/observation/$tables.log)
    # 把之前讀取的最新日期數據加到log文件下
    echo -n "${date[0]}" >> /home/log/hive/observation/$tables.log
    #echo "" >> /home/log/hive/observation/$tables.log
    #$(sed -i '1s/$/2020-04-16 17:03:48.000000000/' /home/log/hive/observation/tablename.log)
    # 調用加載數據腳本,第一個參數爲表名,第二個參數爲分區字段,第三個爲最新的第n個數據
    echo "傳遞的第一個參數是:$tables,傳遞的第二個參數是:$partitions,傳遞的第三個參數是:$n ,${date[0]}!" >> /home/hive/n.log
    /home/hive/loadtb_mid.sh $tables $partitions $n
fi

3、第一次 load into hive表腳本 loadtb_all.sh

#!/bin/bash

echo "------loadtb_all.sh--------"
# 第一個參數爲表名
table=$1
echo "表名參數:$table"
# 第二個參數爲分區字段
partitions=$2
echo "分區參數:$partitions"
# load data directory 
DIR=/home/hive/observation/$table
partkey=(${partitions//,/ })
# 分區數爲$m
let m=${#partkey[@]}

h1="load data local inpath '/home/hive/observation/$table"
h3="' into table observation.$table partition"
allfiles=$(ls /home/hive/observation/$table/*.txt)
echo "allfiles:$allfiles"
echo "allfiles:$allfiles" >> allfiles_all.log
# 遍歷目錄,得到具體分區名稱
for file in ${allfiles};do
	> part_all
	# 取最後一個/後的文件名稱
	h2="${file##*/}"
	echo "h2:$h2" >> allfiles_all.log
	# 去掉文件名後綴.txt
	str=${h2%%.*}
	echo "str:$str" >> allfiles_all.log
	# 分區名稱分割,遍歷文件名
	partvalue=(${str//_/ })
	# 分區拼接字符串
	for (( i=0;i<m;i++ ));do
		echo -n "${partkey[$i]}='${partvalue[$i]}'," >> part_all
	done
	h4_tmp=$(cat part_all)
	h4="(${h4_tmp%*,});"
	echo "$h1/$h2$h3$h4"
	hive -e "$h1/$h2$h3$h4"
	#hive -e "load data local inpath '/home/hive/observation/$table' into table observation.$table partition(partition1=$i,partition2=$i);"
done

$(rm -rf part_all)

3、第N次 load into hive表腳本 loadtb_mid.sh

#!/bin/bash

echo "--------loadtb_mid.sh--------"
# 第一個參數爲表名
table=$1
echo "表名參數:$table"
# 第二個參數爲分區字段
partitions=$2
echo "分區參數:$partitions"
# 第三個爲最新的第n個數據
echo "第三個參數:$3"
echo "全部參數:$*"
N=$(($3))
echo "全部參數:$*"
echo "N爲:$N"
# load data directory 
DIR=/home/hive/observation/$tables
partkey=(${partitions//,/ })
# 分區數爲$m
let m=${#partkey[@]}

h1="load data local inpath '/home/hive/observation/$table"
h3="' into table observation.$table partition"



allfiles=$(ls --full-time -lt /home/hive/observation/$table/*.txt | awk '{print $9}' | head -n ${N})
#allfiles=$(ls --full-time -lt /home/hive/observation/$table/*.txt | head -n ${N})
# allfiles=$(ls /home/hive/observation/$table/*.txt | tail -n ${N})

echo "$allfiles , ${N} , $3 , $(date)" >> /home/hive/n_mid.log
echo "allfiles:$allfiles"
echo "allfiles:$allfiles" >> allfiles_mid.log

# 遍歷目錄,得到具體分區名稱
for file in ${allfiles};do
	> part_mid
	echo "file: $file" > allfiles_mid.log
	# 取最後一個/後的文件名稱
	h2="${file##*/}"
	echo "h2: $h2" > allfiles_mid.log
	# 去掉文件名後綴.txt
	str=${h2%%.*}
	echo "str: $str" > allfiles_mid.log
	# 分區名稱分割,遍歷文件名
	partvalue=(${str//_/ })
	# 分區拼接字符串
	for (( i=0;i<m;i++ ));do
		echo -n "${partkey[$i]}='${partvalue[$i]}'," >> part_mid
	done
	h4_tmp=$(cat part_mid)
	h4="(${h4_tmp%*,});"
	echo "$h1/$h2$h3$h4"
	hive -e "$h1/$h2$h3$h4"
	#hive -e "load data local inpath '/home/hive/observation/$table' into table observation.$table partition(partition1=$i,partition2=$i);"
done

#$(rm -rf part_mid)

執行命令

sh createtb.sh "tablename;field1,field2,field3,field4,field5,field6,field7;partition1,partition2"

運行效果

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章