一开始我们怀疑可能是不是TTL错误,或者什么别的原因导致用户访问的DNS服务器没有刷新新的解析记录。经过一阵紧张的nslookup和dig之后,还是没有能成功找出问题所在。最后修改named.conf当中的日志级别为debug,重新启动之后发现实际上有一个区域的解析记录并没有成功加载。日志大概意思如下:
unknown type "xxx.xxx.xxx" for record NS (大概这意思吧)
打开配置仔细一看,原来该区域下面应该有一个NS解析记录,原本应该是:
NS xxx.xxx.xxx
结果变成了:
NS xxx.xxx.xxx
这一条解析的意思是,当前要解析的域下面的域名服务器是xxx.xxx.xxx。但是由于前面的空格去掉了,结果按照空格划分,第一个表示二级域名的字段从空变成了NS,而记录类型则从NS变成了"xxx.xxx.xxx",而第三个表示解析结果的字段则从"xxx.xxx.xxx"变成了空。于是这一个域名解析记录加载失败,这也导致了后面更改了的解析记录实际上从未被正确加载。之所以域名服务器仍然返回旧的IP,是因为过期时间比较长,在得不到我们的正确解析时,其它的DNS服务器将沿用原来已经有的域名解析结果。
那么,这个空格为什么消失了呢?如果是某个人手动修改的,其手动意图又是啥?经过调查之后发现,原来有人写了一个修改解析地址的脚本,正是这个脚本造成的问题。而之前就已经发现有此问题,解决的办法是通过运行脚本之后手动添加空格来解决,而这一次却忘了。
具体造成问题的脚本命令是read,这个命令十分神奇,会自动根据IFS来分割字段,然后将字段重新组合成一个字符串。用C#来描述,就是:
return string.Join(IFS[0], Console.ReadLine().Split(IFS, StringSplitOptions.RemoveEmptyEntries));
解决的办法很简单,就是将脚本改写成:
while IFS=""; read LINE
do
# something
done < afile
关于IFS在while上面赋值,我想了一下,原因应该是这样的:
如果在独立一行修改,则导致从此之后的运行环境发生改变,会影响并改变后续所有命令的默认行为。而如果在while上面赋值,则因为是folk一个子进程,并且在子进程中运行修改的缘故,并不会导致外部(当前脚本)环境的变化,也不会改变后续命令的默认行为。
这种环境变量影响程序行为的问题,在Windows算比较难以注意到的。一般也就是PATH之类的变量会导致能否找到可执行程序,但很少会影响程序本身正常行为的。对于read来说,默认按照IFS分割并重组输入,确实让初学者难以注意到。
没有评论:
发表评论