项目场景:
在后台调用脚本,并对这个脚本实现循环赋值。最后将查询结果写入同一个log。(for循环中镶嵌 nohup 后台执行)
根据项目需求,我们想通过给查询脚本赋值不同号码,查到号码在表中的情况并将结果写入到log日志中。
问题描述
执行以下调用脚本,会在后台调用查询脚本 check_plan.sh ,结果发现有些号码的查询结果并不完整,存在数据缺失的情况。
arr1=('191*****343' '130*****963')
arr2=('2022101114' '2022101823')
arr3=('20221011' '20221018')
length=${#arr1[*]}
for ((k=0;k<length;k++))
do
nbr=${arr1[$k]}
time_tag=${arr2[$k]}
cur_day=${arr3[$k]}
echo $nbr,$time_tag,$cur_day
nohup sh /apps/bin/model/data_val/test/check_plan.sh $nbr $time_tag $cur_day > /apps/bin/model/data_val/test/check_plan_$(date +%Y%m%d%H%M).log 2>&1 &
done
原因分析:
执行以上脚本,运行情况并不是等第一个号码查询完成,然后再进入第二个号码查询的顺序。虽然是不同赋值情况循环串行执行,但是在相差不多时间同内执行同一个脚本,并将查询结果写入同一个log日志,因此会出现同时写入数据到同一个log日志中的情况,造成数据不完整的错误。
解决方案:
解决问题: 同时将查询结果写入一个脚本。
解决思路:
方案1:循环赋值的过程,等前一个赋值进程结束后再进入再一个赋值进程。(进程串行)
方案2:不同号码查询结果写入不同的log日志(进程并行)
方案1 优点是不会生成过多log日志文件,缺点是进程串行导致运行时间比较长。
方案2 优点是并行运行效率较快,缺点是会生成多份日志文件。
代码实现:
方案1:
在 for 循环中加入 wait,会阻塞当前号码查询进程的执行,直至当前号码查询进程的所有子进程都执行结束后,才继续执行下一个号码进程。
arr1=('191*****343' '130*****963')
arr2=('2022101114' '2022101823')
arr3=('20221011' '20221018')
length=${#arr1[*]}
for ((k=0;k<length;k++))
do
nbr=${arr1[$k]}
time_tag=${arr2[$k]}
cur_day=${arr3[$k]}
echo $nbr,$time_tag,$cur_day
nohup sh /apps/bin/model/data_val/test/check_plan.sh $nbr $time_tag $cur_day > /apps/bin/model/data_val/test/check_plan_$(date +%Y%m%d%H%M).log 2>&1 &
wait #加入wait
done
方案2:
更改查询脚本 check_plan.sh 中的写入文件 file_name,使得一个号码对应一份log日志文件。
nbr=$1
time_tag=$2
cur_day=$3
echo $nbr,$time_tag,$cur_day
global_commmand="beeline --showHeader=false --outputformat=dsv -e"
file_path="/apps/bin/model/data_val/"
file_name="fd_val_result_${nbr}_${time_tag}.log"#一个号码对应一份log日志
file_name_1="fd_val_result_info_$nbr.log"
if [[ ${#condition_rule_234} -gt 0 ]];then
echo "满足规则2,3,4命中并且不满足剔除条件:剔除06:00-9:00有主叫通话记录且被叫为手机号码" >> $file_path/$file_name
#echo "判断是否满足条件(1)入网时间大于7天且小于等于30天" >> $file_path/$file_name step_1_1
condition_online_info=`$global_commmand "use databases;select * from model_range_fd_rule_3_${time_tag} where calling_nbr in ('$nbr') ;"`
if [[ ${#condition_online_info} -eq 0 ]];then
#step_1_1_1
echo "532模型:$nbr不满足条件:入网时间大于7天且小于等于30天,因此没有命中" >> $file_path/$file_name
#step_1_1_1_1
#第一步:查看业务信息中间表的具体的入网时长(证据说明问题)。
result_online_info=`$global_commmand "use databases;select * from all_mobile_user_info_${cur_day} where calling_nbr in ('$nbr') ;"` >> $file_path/$file_name
#step_1_1_1_2
#第二步:判断是否有被"业务信息不正常的结果表"命中
result_untj_info=`$global_commmand "use databases;select * from model_fd_online_result_info30 where calling_nbr in ('$nbr');"`
if [[ ${#result_untj_info} -gt 0 ]];then
echo "输出满足条件的号码命中批次(业务信息不正常)" >> $file_path/$file_name
echo "$result_untj_info" >> $file_path/$file_name
else
echo "没有被(业务信息不正常)命中??? 大问题了,代码有问题了(哭.jpg)"
fi
else
#step_1_1_2
echo "满足条件(1)入网时间大于7天且小于等于30天" >> $file_path/$file_name
echo "满足条件的号码命中批次(业务信息正常)如下" >> $file_path/$file_name
result_tj_info=`$global_commmand "use databases;select * from model_fd_stat_real_info30 where calling_nbr in ('$nbr') and etl_cycle_id='${cur_day}';"`
echo "$result_tj_info" >> $file_path/$file_name
fi
fi