好多大佬都利用&符号加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