最近有個(gè)需求,就是SpringBoot提供一個(gè)web接口給業(yè)務(wù)方,業(yè)務(wù)方傳入?yún)?shù)調(diào)接口,接口去執(zhí)行hive離線計(jì)算,一般可能是說直接用jdbc去連hive執(zhí)行hive操作,但是這種方案,對(duì)于單個(gè)任務(wù)可能還是可以的,如果對(duì)于10個(gè)維度的數(shù)據(jù)統(tǒng)計(jì),那這個(gè)代碼寫起來就坑了。。所以還是想著,把所有hive腳本都放一個(gè)shell腳本里,java調(diào)接口的時(shí)候直接去執(zhí)行這個(gè)腳本,而且不需要等待結(jié)果,所以我采取這種方案。
但是,想法是好的,現(xiàn)實(shí)很殘酷。
問題拋出:java無法調(diào)hive腳本無法執(zhí)行。
這個(gè)問題卡了一天了,期間也問了一些朋友,都沒遇到過這種需求,所以沒有辦法,只能自己來搞??ǖ脑蛟谀睦锬??如果直接在java代碼里調(diào)hive腳本執(zhí)行的話,會(huì)出現(xiàn)如下問題:

百度、谷歌也搜了,都沒搜到我要的答案。真是坑。期間我也想過是不是權(quán)限的問題、或者是不是沒找到hadoop路徑之類的問題,都配置上去了,不起作用。。

所執(zhí)行的test.sh腳本中,只放了一個(gè)清空hive表的語句

搞了一天,不行,該試的方法都試過了,咋辦呢?甚至連直接通過java代碼去執(zhí)行hive語句,但是因?yàn)樯a(chǎn)環(huán)境中是一個(gè)離線統(tǒng)計(jì)的腳本,腳本語句就大幾百行,如果轉(zhuǎn)成java去調(diào)用,這工作量可想而知。。而且,腳本中不單單是hive語句的腳本,還有hadoop的腳本,比如刪除hdfs某個(gè)文件夾、執(zhí)行某個(gè)已經(jīng)寫好的mapreduce任務(wù)……等等這些,反正就是通過java好干難(方言:艱難的意思),所以我心想,不行,得解決這個(gè)問題。所以我又重新梳理了一下問題,報(bào):“Unable to determine Hadoop version information”,這個(gè)錯(cuò)誤是在hive啟動(dòng)腳本中的,所以問題還是回到了原來的思路:是不是直接通過java調(diào)這個(gè)腳本,可能無法加載hadoop環(huán)境,既然不能直接調(diào),那間接的是否可以呢?
問題解決:間接法
解決思路:
① Java先調(diào)一個(gè)腳本,在這個(gè)腳本中專門接收參數(shù),并將參數(shù)寫入指定文件中;
② 然后再寫一個(gè)shell腳本來實(shí)時(shí)監(jiān)控這個(gè)參數(shù)文件的變化,如果文件內(nèi)容有變化,則直接調(diào)用真正的hive腳本取執(zhí)行
代碼如下:
第一步:創(chuàng)建一個(gè)接收參數(shù)的腳本acceptParam.sh:
rm -rf /root/single_prod/data/single.txt
echo $1 >> /root/single_prod/data/single.txt

第二步:通過java代碼去調(diào)用,看看能否將參數(shù)寫入指定的文件中

第三步:最重要的一步,寫一個(gè)實(shí)時(shí)監(jiān)控腳本monitor.sh:

#!/bin/bash
# $param1 需要監(jiān)測的文件
# $param2 存放文件md5值,用于判斷文件是否更改
param1='/root/single_prod/data/single.txt'
param2='/root/single_prod/data/single.txt.md5'
if [ ! $param1 ] || [ ! $param2 ] || [ ! -e $param1 ] ; then
echo "\$1 or \$2 is file"
exit
fi
# 生成md5驗(yàn)證文件
function creatMd5file()
{
md5sum -b $param1 > $param2
}
# 判斷文件是否存在
if [ ! -e $param2 ] ; then
creatMd5file $param1 $param2
fi
while(true) ; do
# 檢測文件是否修改,$?返回1 表示修改, 0表示未修改
md5sum -c $param2 --status
if [ $? -gt 0 ] ; then
echo "執(zhí)行吧"
for line in $(cat $param1)
do
echo "讀取文件內(nèi)容為:"$line
sh /root/single_prod/test.sh $line >> /root/single_prod/logs/test.log
done
creatMd5file $param1 $param2
fi
# 每過3秒檢測一次
sleep 3
done
第四步:驗(yàn)證
[root@master1 single_prod]# nohup sh monitor.sh >> monitor.log &

終于大功告成了,真是不容易,搞了一天半。。。