Posts 坑你的不止是换行
Post
Cancel

坑你的不止是换行

今天碰见的一个坑我觉得应该记录下来,对自己有个提醒或者对其他朋友也有个警示作用。大家就当看个小故事吧!

天坑查找

情况总结是这样,有个命令cmd,有个参数-p,正常调用形如:cmd -p a,b,c,d test.txt -p可以接带逗号的参数,因为参数太多,不可能手打,所以把这些参数存在了一个文件里,然后二次调用这个文件,cmd -p $(paste -s -d , para.txt) test.txt,这样通过二次调用para.txt就可以随意设置-p的个数,长度了。

问题来了,前端反馈需求又要改(是不是感觉很熟悉,而且为什么说又呢?)。于是让前端更新了这个para.txt。拿到更新的参数文件以后,因为知道这是他们通过windows或者excel之类操作的,在确认para.txt是纯文本之后,依旧小心翼翼的dos2unix把这个文件更新为unix格式的形式。而且还顺带稍微看了下会不会有其他怪异的字符,确认没有后,把para.txt更新到生产环境。

于是乎悲剧就产生了,果断的报错。具体到命令提示就是一直提示类似于a,b,c,d,....... Filename too long,于是感到奇怪,-p明明是个参数,为什么一直提示是File呢?更新前后的参数个数并没有明显增加啊?于是尝试了下人为减少para.txt里面的行数,一直出错,一直到行数很少的时候才不报错。难不成真是行数太多的原因??直觉告诉我不应该啊,难道是因为shell的原因?因为我用的是zsh,某些特殊情况发生过zsh和bash结果不一样的情况,于是尝试切换到bash模式,错误依旧。直觉还是告诉我可能还是文件的问题,于是dos2unix后,又cat para.txt > para_new.txt重新生成一遍,用原始的shell生成的文件试试呢?还是报错。

已经报错N次了啊,不科学啊,在这里我还是相信dos2unix处理后的正确性。于是我在para.txt前面取了100行,然后一直重复,直到比原始的文件大不少,这次居然没有报错了。看来这个too long什么的不存在啊!还是哪个地方是有问题的啊。然后我又取200行一直重复,也正确,然后继续加大,果然报错了。看来是文件本身一定有什么不对的地方。然后我再仔细重复看了这些报错信息,因为error提示太长了,以前一直没认真看,只注意到末尾的error提示Filename too long,这次把注意力集中到error的开头,果不其然每次出错的信息的开头都是一模一样的,都是’,BRCA2,……,..Filename too long’,这时候就在想为什么都是出现同一个错误呢?于是进去文本去找这个BRCA2,看起来也没什么怪异的地方啊?于是尝试在BRCA2这一行以及上下一行反复的删除测试,发现确实问题就在这个地方,只要删除BRCA2前面的一行,问题就不存在了。

其实,当测试到这里我突然就知道了,因为对于这个文件我使用了paste -s -d , para.txt这个命令,是把文本的所有行都连成一个字符串,类似于编程领域的join函数或方法。而这个字符串将作为cmd的-p参数,所以这个字符串肯定连接以后就出现了问题!

坑你的还有空格

因为因为因为,中间有空格符号,所以-p 后面的字符串在shell里面就不是一个字符串了,因为有空格就变成多个字符串了, 类似-p a,b,c ,d,e,f...,正式因为c后面有空格,所以才把c后面的信息当成了文件名。知道这个原理,结合error的表头信息可以确定,brca2前面的那一行一定是有空格符号。

好了,进入文件,找到这行,果然就是有空格符号,删掉之,重新运行,OK!

总结

其实这个问题在今天花了我可以说很多时间以及心情,按道理对shell应该是熟悉的,一开始就应该知道为什么会出现这些错误。但是从一开始却没考虑到空格这个因素,就是因为命令里面是嵌套着命令的形式运行的,而且嵌套的命令的数据又是前端提供我再处理的,中间隔了很多步骤,导致我的注意力一直停留在文件的合法性上,包括我还考虑了zsh,bash等,没有去从文件里面数据的情况多样性去考虑,导致注意力被分散了,而且error信息太长,我只注意到了最后的Filename too long,没去注意它的起始部分(因为要翻页,嫌麻烦),这也是我的一个失误,如果一开始注意到了起始部分,可能就能发现数据本身的问题。

这让我想起了很多人都反应的数据格式问题,只要数据在不同系统中路过一次,那么就有坑的存在,比如windows和unix之间只要数据有过接触,其实就很危险,当然这很多时候是换行符号的问题,所以才有了dos2unix这种工具的流行。 但是,同时还有一个更大更深的坑,那就是人工的存在。只要数据涉及到人工之间的操作,那就将变得无比危险,因为各种各样的情况你根本考虑不到,空格,大小写,半全角,甚至是字母的I和l和数字1,字母O、o以及数字0,以及怪异的各种符号等等等等等等…这些情况都是我在实际生产中遇到过的,每次发生这类问题时候,一开始是如临大敌,觉得是不是程序哪些地方设计严重失误,没有考虑周全,然后赶紧查找原因,心情紧张,不知道会不会面临着重构的风险,到最后找到涉及问题的代码,知道原因的时候,总有种想砸键盘的冲动,然后跟前端人员沟通出现错误的原因,大家都尴尬的一笑,额,原来是这么回事啊,没事,小事情,2秒就解决了,重新运行一次! 然后,下次,继续重复上面的剧情,直到某一方实在受不了,要提出彻底解决的方案。

其实像这种问题,双方都有过错,前端不按sop,不按规则做事,那么神仙的代码也拯救不了。后端的robust性能不够,虽然考虑到方方面面很困难,但是出了问题应该要考虑到要及时能够定位,再进行二次解决。虽然理论上都好说,但是实际上,我想大家都知道能够做到及时沟通以及能够及时解决问题的难度。所以就本人而言,工作上越来越喜欢独立去搞项目,就是因为不想受外部太多的影响,什么东西都可以自己去构架以及实现,有问题那也是绝对的自己的问题,那要自己去承担以及解决。这有时候,我想也未必不是一个好方案把。毕竟,现在整个IT领域的前端和后端的研发,都提倡一个前端和后端的独立、隔离。我想其中的缘由也跟我的想法差不多吧!

最后,这个事情还是很有收获的,不止是知道错误的原因,而是碰见问题,一定不要急,要从各个方面的源头去思考。比如这里,如果给你一个命令cmd -p a,b ,c test.txt直接去运行,出错后可能你不需要一秒钟就知道,c这里是错误的,但是嵌套一个命令,命令在调用一个外部文件,出现同样的错误,却无法做到1秒钟就解决。就是因为我的注意力没集中,没去从问题的本质去思考,被其他因素影响了。当然啦,也同样告诉我们,完成同样的事情,还是做的越简单越好,绕的弯多了,迟早要翻车。

OLDER POSTS NEWER POSTS

Comments powered by Disqus.

Contents

Search Results