好多大佬都利用&符號加for循環將其放在後臺執行,有利有弊,代碼如:
#!/bin/bash
for i in `seq 100`;do
sleep 1 &
done
這樣雖然執行了一百次循環,但是每次的sleep都放在了後臺,一秒不到就結束了 而且完全不可控,我想要下載東西時,同時創建了大量連接放在後臺 對於cpu內存都有不小的壓力,同時大幅度佔用帶寬.
還有大佬寫了個難以理解的可控的方式,每次同時放在後臺一定數量的進程,但是有點難以理解.
某天,再寫一個數據備份腳本的時候有了新的想法,由於HBASE中有大量的表,單條備份太慢,同時放在後臺Hadoop資源不夠用,同時還要知道那些表備份成功或失敗,只能放在後臺一條命令遠遠不夠,所有進程全部卡死,思考後將備份語句及判斷寫在函數中,利用for循環將函數放在後臺.同時設置變量加判斷方式檢查放在後臺的進程數,如果足夠多則執行wait等待進程執行完畢,腳本如下.
#!/bin/bash
# 刪除三天之前
# 70張表24分鐘
# 需要安裝bc命令 並且HBASE及Hadoop添加了環境變量
LogDir='/var/log/data-backup'
mkdir $LogDir
LogFile='data-migration'
start(){
source /etc/profile >/dev/null
BackupTime=`date +%F`
Backup_hbase_command='org.apache.hadoop.hbase.mapreduce.Export'
HDFS_path='/backup'
local_path='/backup'
# 此參數爲備份文件保存幾天
remove_day='3'
# concurrent_number 同時放在後臺執行的進程數量
# 此參數爲同時運行備份進程的數量,增加會提高備份速度但是很消耗Hadoop資源,每條都會創建一個MapReduce任務,可以根據當前集羣配置適當增加以提高速度
concurrent_number='1'
if [ ! -f ${LogDir} ];then
mkdir -p ${LogDir}
fi
}
# HBASE 備份
# 將被放在後臺執行的函數
backup_command(){
echo "[ `date +%F-%T` ] $i start backup,this is a tables $a"
# 此處的$i則是for 循環體中的變量 i
hbase ${Backup_hbase_command} $i ${HDFS_path}/${BackupTime}/$i >>$LogDir/${LogFile}-$a.log 2>&1
# 判斷上一條結果是否成功
if [ $? -eq 0 ];then
echo "[ `date +%F-%T` ] $i backup sucess"
else
echo "[ `date +%F-%T` ] $i backup error"
fi
}
HbaseBackup(){
echo "[ `date +%F-%T` ] Hbase backup start"
echo "list" |hbase shell >/dev/null
if [ $? -eq 0 ];then
echo "HBASE status is a: started"
else
echo "HBASE statua is a: stoped!"
exit
fi
a='1'
for i in `echo "list"|hbase shell |sed '1,6d'|sed '$d'|sed '$d'|sed '$d'`;do
# 依舊是利用了for循環,但是不執行單條命令,將命令寫進函數中,直接將函數放在後臺
backup_command &
# 判斷當前取餘是否等於0,如果是則放在後臺的函數足夠多,判斷爲真則執行wait ,wait作用是等待後臺的進程執行完畢,然後重新開始了循環
if [[ `echo "$a % ${concurrent_number}"|bc` == 0 ]];then
wait
a=`echo "$a + 1"|bc`
else
a=`echo "$a + 1"|bc`
fi
done
}
data_export_local(){
echo "[ `date +%F-%T` ] hdfs to local started"
hdfs dfs -copyToLocal ${HDFS_path}/${BackupTime} ${local_path}
echo "[ `date +%F-%T` ] hdfs to local stoped"
}
hive_backup(){
echo "[ `date +%F-%T` ] hive backup start"
backup_path='/backup/hive'
backup_time=`date +%F`
if [ ! -f ${backup_path} ];then
mkdir -p $backup_path
fi
hdfs dfs -copyToLocal /user/hive ${backup_path}
# 手動重複執行此處會有提示輸入 y 但是不可見
mv ${backup_path}/hive ${backup_path}/hive-${backup_time}
hive_remove_time=`date -d "${remove_day} day ago" +%F`
rm -rf ${backup_path}/hive-${hive_remove_time}
echo "[ `date +%F-%T` ] hive backup end"
}
remove_time_backup(){
remove_time=`date -d "${remove_day} day ago" +%F`
hdfs dfs -rmr ${HDFS_path}/${remove_time}
rm -rf ${local_path}/${remove_time}
}
start >>$LogDir/${LogFile} 2>&1
HbaseBackup >>$LogDir/${LogFile} 2>&1
data_export_local >>$LogDir/${LogFile} 2>&1
remove_time_backup >>$LogDir/${LogFile} 2>&1
hive_backup >>$LogDir/${LogFile} 2>&1