今年开发过一次shell脚本的需求,在获得了一个简单模板的基础上开发符合需求文档要求的处理内容。
开发的过程很顺利,自测没有出现大问题。但是实际部署就遇到棘手的情况了。
某基线界面化配置 首次部署时发现通过界面配置方法,配置文件里的配置项行后面出现注释格式的错误信息(;bash: -F;: command not found )问题
经过分析,定位到在update_config.sh脚本模板里有关于注释处理的内容,某行是
comment=`sed -n ''${name_linenum}'p' ${w_filepath} | sed -r 's/^[[:space:]]*(.*[^[:space:]])([[:space:]]*)$/\1/g' | $UNIXAWK -F';' '{print $2}'`
这行的意思是将各式如下所示
Config=123 ;this is a config
的配置行里的“this is a config“提取出来,如果匹配不到就当做没有注释。
此处的$UNIXAWK 定义值在该脚本内部没有定义。由于本次需要不需要处理注释,这部分注释处理在自测suse环境,环境都没有报错(即是comment返回空,后续脚本代码会当做没有注释来处理),为了保持update_config.sh结构的完整性,开发阶段并没有对该功能删除。
但是某地现场使用的某redhat操作系统出现了返回为 “bash: -F;: command not found”的情况,这就导致配置文件配置值后添加了 内容。而在字符串内容配置值读取的时候所用函数不会自动过滤掉该行“;”后的信息,配置值就把改垃圾内容读进去了。
现场通过在执行用户的.bash_profile中增加UNIXAWK=awk的环境变量配置后,将此问题解决。此时实际执行的该行shell语句是
comment=`sed -n ''${name_linenum}'p' ${w_filepath} | sed -r 's/^[[:space:]]*(.*[^[:space:]])([[:space:]]*)$/\1/g' | awk -F';' '{print $2}'`
想不到竟然sed语句在不同操作系统处理方式还不一样。
我做了如下测试
直接执行命令行效果如下:
suse修改前(返回空):
-bash-3.2$ sed -n ' 94 p' /home/sth/etc/sthcfg.ini | sed -r 's/^[[:space:]]*(.*[^[:space:]])([[:space:]]*)$/\1/g' | $UNIXAWK -F';' '{print segment}'
suse语句修改后(返回空):
-bash-3.2$ sed -n ' 94 p' /home/sth/etc/sthcfg.ini | sed -r 's/^[[:space:]]*(.*[^[:space:]])([[:space:]]*)$/\1/g' | awk -F';' '{print segment}'
redhat修改前(返回错误信息):
-bash-4.2$ sed -n ' 94 p' /home/proto10/etc/sthcfg.ini | sed -r 's/^[[:space:]]*(.*[^[:space:]])([[:space:]]*)$/\1/g' | $UNIXAWK -F';' '{print segment}'
bash: -F;: 未找到命令...
redhat语句修改后(返回空):
-bash-4.2$ sed -n ' 94 p' /home/proto10/etc/sthcfg.ini | sed -r 's/^[[:space:]]*(.*[^[:space:]])([[:space:]]*)$/\1/g' | awk -F';' '{print segment}'
redhat在.bash_profile中增加UNIXAWK=awk的环境变量配置修改后(返回空):
-bash-4.2$ echo $UNIXAWK
awk
-bash-4.2$ sed -n ' 94 p' /home/proto10/sthcfg.ini | sed -r 's/^[[:space:]]*(.*[^[:space:]])([[:space:]]*)$/\1/g' | $UNIXAWK -F';' '{print segment}'
由此可见,同样是sed语句里某变量缺少定义,suse操作系统可以返回空,而redhat操作系统却返回了错误信息。
我们可以得出一个重要警示:
Shell脚本开发一定要结合操作系统!