shell 多進程 簡單方式

好多大佬都利用&符號加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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章