好多人在聊到脚本语言时总说它不像编译型语言那样可以灵活的打断点进行调试,其实这个是误解,今天宝王爷告诉你一个exec命令,不仅可以灵活对脚本进行分段调试,还可以结合sh -x命令对该段脚本中每一步的执行结果进行查看,非常方便!
一、exec内建命令并不启动新的shell,而是用被执行的命令替换当前的shell进程,并将老进程的环境清理掉,在exec之后的其他命令也不再执行。
关于exec退出当前shell的场景,举例如下:
1)[root@rhel12180 bool]#exec echo hello
结果是在输出hello后,直接退出当前登录的shell,也就是当前窗口的连接会断开。
2)dd.sh脚本的内容如下:
for i in A B C D
do
echo -n "$i:"
for J in `seq 10`
do
if [ $J -eq 5 ];then
echo
continue 3
fi
echo -n "$J"
exec echo hello
done
done
echo
执行dd.sh脚本后的输出如下:
[root@rhel12180 bool]# sh dd.sh
A:1hello
[root@rhel12180 bool]#
也就是在运行至exec echo hello处时直接退出了当前的shell,即dd.sh
3)x.sh的内容是
[root@rhel12180 bool]# cat x.sh
exec echo -n bowen
修改dd.sh的内容如下
[root@rhel12180 bool]# cat dd.sh
for i in A B C D
do
echo -n "$i:"
for J in `seq 10`
do
if [ $J -eq 5 ];then
echo
continue 3
fi
echo -n "$J"
sh x.sh
done
done
echo
然后运行dd.sh脚本,结果如下:
A:1bowen2bowen3bowen4bowen
B:1bowen2bowen3bowen4bowen
C:1bowen2bowen3bowen4bowen
D:1bowen2bowen3bowen4bowen
也就是说在调用dd.sh脚本时,在执行sh x.sh这一步时并没有像2)那样直接退出dd.sh,实际上是退出了x.sh,然后继续执行dd.sh中其他的部分,所以输出了完整的循环过程执行的结果。
二、
exec
exec 3
exec 3<&- 关闭文件标识符
exec 3>file 将写入指定文件标识符的内容写入file(这个不需要先有文件file)
exec 4<&3 创建文件标识符3的拷贝4
备注:
1)和1>,2>比较可知exec 3>file命令就是将标识符的内容写入file,而如果箭头反过来exec 3
2)在标准输出和标准错误合并的命令中2>&1,可以理解&1代表标准输出标识,前面加上2>则是表示将标准错误也写到同样的标识中,即合并输出,所以从这个角度理解exec 4<&3就很容易了,&3表示标识符3,左箭头表示对标识符本身进行操作,即复制功能。
三、exec在调试脚本中的使用
shell脚本有一个特点,很多时候运行时报告的错误,其实位置不一定准确,我曾经使用sh -x rating.sh执行调试运行时,系统提示221行缺少了`"',但实际检查时发现这一行并没有问题,最后逐步检查发现是在56行缺少了一个”导致。
如果脚本比较少,能很快定位到语法的错误位置还好,万一脚本已经写得很多了,超过了上千行,这个时候就需要使用exec了。举例:
sqlplus "$user"/"$passwd"@"$service" <table
select sum(aimdb_deduct_value_cur) as deduct_value_cur from ad.abm_CAbmCredit_$MONTH10;
select nvl(sum(c.金额),0) as ras_value
from (select '优惠' 类型, nvl(sum(a.aimdb_discount_fee),0) 金额,count(1) 条数
from ad.ras_crasprombill_$DATE a
where exists (select 1
from ad.ras_crasresbill_$DATE b
where a.aimdb_bill_id = b.aimdb_bill_id
and b.aimdb_begin_date>=$DATE) c;
exit
EOF
exec echo debug
if [ -f table ];then
deduct_value_cur=$(sed -n '/deduct_value_cur/{n;p}' table|awk '{print $1}'|tr -d ' ')
fi
echo "$deduct_value_cur"|tee -a monitor.log
上面这一段脚本中添加了exec echo debug之后,运行时后面的斜体部分就不执行了,结合sh -x调试命令,就可以进行准确定位。
如果前面的脚本运行没有报错,就可以将exec echo debug位置后移,直到出现了和整个脚本运行后报相同的错为止,通过这种方法就将错误限定到了一小段脚本范围内了,再检查sh -x输出的每一步的结果,此时定位问题就非常方便。
--END--
鉴于数据分析能力越来越成为每个职场人的必备技能,所以我最近新打造了本垂直公号,这里聚焦分享数据分析和脚本编程的干货,欢迎大家都转起来,让更多的人来一起碰撞,交流,提升!