程序员那些悲催的事儿
在StakeOverflow上有这样一个贴子叫“Confessions of your worst WTF moment”(WTF就是What the fuck的缩写),挺有意思的,我摘几个小故事过来,希望大家在笑过之后能从中学到什么——所有的经验都是从错误中来的(我在其中加了一些点评)
我们公司的软件是给警察局用的,那是一个对用来处理被逮捕的人的系统,此系统还需要收集脸部特征和指纹信息,并且,这个系统和会向FBI的系统提交这些信息。当我们在测试这个系统的时候,我们一般都是用我们自己的指纹,当然,数据库联着的是我们的测试数据库。不过,有一次,在我们测试完后,我们忘了把系统切换回生产库,于是我们的测试数据库就联上了生产环境,于是我们的指纹信息和照片就散布到了其它系统中……清除我们警察局这边的还好办,但是,你需要波士顿警察局警司去法院签字才能从FBI的数据库中清除我们的信息。
点评:测试环境和生产环境的数据不要混在一起。
有一次,我需要向新系统中导入一堆数据,因为数据量太大,需要5个小时,只能在夜里来干,在系统需要正式使用前2个小时,数据导完了,此时是凌晨4点。随后,我需要删除一些数据,于是我在SQL命令地上输入了“DELETE from important_table; where id=4”。是的,我没有看到哪里还有个分号,天啊。
点评:这就是加班工作的恶果。另,在delete之前最好先做一次select。
我把我的管理员口令提交到了一个开源软件的源码里。
点评:1)版本管理器里的东西是删不掉的。2)一些用户和口令要hard code在代码里,所以,不要混用代码使用的权限和管理员的权限,小心管理程序的运行权限,为其注册专门的用户。
我为一个很大的银行开发软件,在我的代码里,我为一段理论上根本不可能执行到的代码加了一个报错信息。有一天,不可思异的事发生了,这条报错信息显示在了该银行的1800个分行的超过10000个终端上——“如果你看到这个信息,说明整个系统被Fuck了,回家吧,祝你过得愉快!”
点评:“假设是恶魔”,Assume意为Ass – u – me,意为——搞砸你和我。对于一些关键东西,永远不要做假设。小心你言语中的——“可能、应该、觉得、不应该”等词语,程序可不认这些东西。
我远程登录到服务器上加几个防火墙规则。第一件我想干的事是在不允许任何人的任何连接,第二件是,为某个端口打开访问权限。不过,我在做完第一件事后就把配置保存了,结果其生效了……
点评:这样的事经常发生,做远程网络管理的人多少会有那么几次发生这样的错误。在你将你的网络配置生效前,你得想一想,断线了你是否还能登得上去。改配置不要太冲动,生效前检查几次。
我们的代码中有一个模块完美地工作了很多年了,只是代码太乱了。我说服了我的老板,我可以重写这个模块,于是我花了三个星期来重写这个模块。今天 ,我还记得,我的老板站在我的后面看着我,而我在在流着斗大的法汗珠去fix被我重写的“超级漂亮”的那个模块中一个接一个的bug。从那以后,我再也不重写代码了,除非有重大的利益。
点评:这就所谓的屠宰式编程。这个案例告诉我们两个道理,1)维护代码要用最最最保守的方法来进行。2)重构代码前要像一个商人一样学会计算利益。当然,ThoughtWorks的咨询师一定会告诉你TDD,结对,极限等等方法告诉你如果实践重构。但我想告诉你,一个程序在生产环境里运行好几个年能没有问题是一件很不容易的事,那怕其中的代码再烂,你再看不过去,你都要有一个清醒的头脑明白这几点,1)软件的运行质量是远远大于代码质量的,2)你的测试案例是远远小于生产环境的,3)软件的完美的质量,是靠长时间的运行、测试和错误堆出来的,而不是某种方法论。
————————————————
相信大家做程序员这一生中也有很多发生在自己身上的悲催的事儿,欢迎分享。我先分享几个我亲身经历过的事。
一个发生在我的领导身上。
我98年刚参加工作的时候,在某单位网络部门,一次,我们整个部门去给下属单位培训Cisco路由器,结果我们发现带去培训地点的设备少带了集线器HUB,设备连不起来。于是领导很不高兴,质问我们为什么没有带集线器?那几个对领导平时就不满的老员工说办公室里没有集线器了,都借给别的部门了。领导想了想,问我:“陈皓,我记得上次我给过你个集线器”,我说,“好像没有吧,我记不起来了,什么牌的?几口的?”,领导说:“什么牌子想不起来了,不过我记得那个集线器是一个口的”。“一个口的?!”,我心里嘀咕着,“真敢说啊”。但我不敢接话了。那几个老员工来劲了——“哪有一个口的HUB啊,一个口的怎么联两台电脑啊?”,领导说:“用两个一个口的不就行了”。领导这话一出,全场一片寂静,无言以对……
后来:我们所有的组员都离开了我们的这个领导,我们的这个领导今天还在那里工作。我想告诉大家,很多时候该走的是领导(包括外企,我上一东家正在裁人,不过我觉得该被裁掉的应该是那些经理)。我们的领导经常出这样或那样的笑话,这让我随时随地地警醒自己——“不要当一个被人笑话的经理”,于是,今天我还在努力地学习技术。
另一个发生在我身上
刚刚接触Linux的时候,还不是很懂,那时的PC还只有奔3,编译公司的程序好慢啊,有时候为了调查一个问题,需要不断地打log,来来回回地编译,很不爽。直到有一天,硬盘不够了,df一下,发现/dev/shm还有空间。于是,把全部程序copy了过去,发现编译起程序超快无比,爽得不行。于是就把工作环境放在/dev/shm下了,连开发都放在这里了。这一天,开发一个功能,改了十来个文件,加班很晚,觉得基本搞定,大喜,回家睡觉。第二天一来,发现/dev/shm下空了,一个文件都没有了,问同事,同事不知,同事还安慰我说,上次他的文件也不知道被 谁删了,于是我大怒,告老板!老板也怒,发邮件到整个公司质问大家谁删了陈皓的程序,无人应答。IT部门答,“昨晚唯一的操作就是重启了linux服务器,什么也没干,不过我们天天备份服务器,可以恢复”,IT部门问我丢的文件在哪个目录下?于是,我reply to all – “在/dev/shm下……”,哎,人丢大发了……
后来:我很感谢我以前犯的这个错,从那天以后,我开始立志学好Linux,这个错误让我努力,让我发奋。所以,我想告诉大家——尤其是刚出道的程序员,你们要多多犯错,要犯错那种丢死人的错,这样你才会知耻而勇。
再来一个发生在我同事身上的
01年,我们开发银行系统,在AIX上开发,RICS6000很贵,只能在客户那里开发,开发进度很紧张,慢慢地硬盘就不够用了,系统中有大量的垃圾文件,于是需要清除一些文件,于是有一个同事写了一个脚本,可以自动清除的各种不重要的文件,里面有一条命令大致是这个样子“ rm -rf ${app_log_dir}/*”,意为清除程序运行的日志。为了使用这个脚本,需要在root用户下运行,一开始还不错。直到有一天,某人一运行,整个根就没了。搞得整个团队只能用一周前的备份重写已写好的代码。后来,才发现原因是${app_log_dir}变量为空,于是成了“rm -rf /*”……
后来:这个事后,我的那个同事,把rm命令改了名,并自己写了一个rm命令,把删除的文件先放到一个临时目录下。而我也因为这个事情,到今天,每次当我在root目录下使用rm时,敲击回车的手都是抖的。(另,rm时永远使用绝对路径)这里,我想告诉大家——犯错不可怕,可怕的是不会从中总结教训,同一个错犯两次。
欢迎分享发生在你身上那些悲催的事。
(本文请勿用于商业用途,转载时请注明作者和出处)
(转载本站文章请注明作者和出处 酷 壳 – CoolShell ,请勿用于任何商业用途)
《程序员那些悲催的事儿》的相关评论
“2)你的测试案例是玩玩小于生产环境的” <-博主想说的是不是“往往”?
挺有意思也很深刻,值得新手注意。
Kao,我在后台里写的是“远远”,怎么前面显示是“玩玩”,这是怎么一回事?!
用rm的,可以用这句话来形容:夜路走多了,总会遇到鬼……..
我也试过把整个/lib 给rm了
几乎不用rm,都用mv xxx /tmp
我上次准备把新写还没来得及checkin的文件拷到home目录,手快忘了打“~”了,就变成了这样:copy aaa.{h,cpp} 。。。几k行的cpp啊。。
“rm -rf”应该加上 “–preserve-root”
rm -rf –preserve-root ${app_log_dir}/*
看了这文章,想想现在身边的“悲催”的事儿还蛮多的,几乎天天都有那么一两起。。。 :D
@pnhongdong
握下手,我也曾经把/lib目录用rm -rf给删掉了
^_^,有一次在客户那儿,刚刚把系统导入了sun机器;一时心好,想把地上的电线理下,结果把电源插头踩坏了,那可怜的solaris系统立刻见了上帝;好不容易把solaris整好,刚导好的系统也坏了….杯具。
这个文章必火,支持作者,总结的很好 ;)
与我心有戚戚焉
这篇文章不错啊
做开发的不用代码版本控制的孩子们,伤不起啊,伤不起。
^_^,我用rm时候也手抖啊。
确实很有趣~
加班的恶果:
有一回,在公司熬夜加班,凌晨3点多了都。脑子迷迷糊糊的写了5行代码。第二天早上回来一看,5行中有3行是错的。:(
做程序员真的好惨啊……经常加班,人都加坏了。
刚开始学AIX时,不懂,结果在/ 下运行了一个 rm -rf *,然后就得找人借盘重装了。
看了好多篇……这是最有意思也最有教育意义的一篇,博主加油!
曾经远程禁用过3389端口
如果你的服务器放在国内机房,千万不要使用数字命名某个文件夹,如果你的文件夹名字是 64 的话,可能会莫名其妙被删除。
1)版本管理器里的东西是删不掉的。
这是版本管理器的问题, git在push之前删掉很容易。
我梦游把一台服务器远程桌面关了。后来从另一台服务器执行WMIC 开启远程桌面,然后重启,就省跑机房了
若干年前,那是刚毕业出来工作的前几个月,参加一个项目,VB + SQL Server的COM+应用系统开发,发生了一个事故,我写的sql代码里,有一部分是减去一个数,结果杯具了,发送到数据库服务器的语句里包含了”–“,结果后面的条件全给系统忽略,数据全更新成相同的值。。。好在事情发生在上线前的数据准备阶段。至今记忆犹新
这篇很好,顶!
我也干过改iptables 的配置,搞得自己上不去了。
别人跳过的坑一定要绕行啊
P.S. 第一行中StakeOverflow应该是StackOverflow吧
这样一样不行,会把 / 下面删得光光的,因为星号扩展成了 / 下的目录。
好奇答案是什么?
很有意思
记得在这里发过一次了:执行了sudo mv /etc/passwd{,bak}
曾經要清掉隨身碟, dd if=/dev/zero of=/dev/sda bs=512 count=1000, 然後主硬碟就杯具了….
@cmonkey
我也干过~然后让别人远程跑到机房重启…..悲催啊~
确实,平时的大量错误可以积累宝贵的经验,程序员产生于长期的积累
我也有发生过悲催的事:
大四给公安局做一个项目,一次公网链接的数据库不知道怎么,IP写成了实验数据库的地址,结果所有公安局民警通知的工作日记少一个星期,一个哥们帮7、8个人写了一周的日记没有了,想自杀,我们也是很后怕的,毕竟人家有Gun的。
多年前,也 rm -rf * 了,整个开发程序全没了,靠,还没有版本控制, 还后前一天我自己备份过,损失不大
我原来的一个公司,我们用的是mysql数据库,当时我需要改一个用户的数据,当时写了一条sql语句,本来应该是“update u_user set money=1000 where uid=111”,结果我悲催的写成了“update u_user set money=1000 and uid=111”,要是在其它数据库就会报错,没想到mysql的兼容性太好了,执行成功了,结果我改变了全部用户的金币数量。What the Fuck。
好不容易做了一首满意的曲子,导出MP3后,想备份一下,本来想写 tar cvfz aaa.tar.gz aaa.xm aaa.mp3 (aaa.xm是源文件),结果中间那个 aaa.tar.gz 忘打了……
How to shoot yourself in the foot with Unix:
% ls
foot.c foot.h foot.o toe.c toe.o
% rm * .o
rm:.o no such file or directory
% ls
%
什么。。
以前搞嵌入式开发,喜欢把跟目录挂到NFS上,然后从目标板访问,包括读写.直到有一天,我在挂载目录上rm -f了……从此再也不挂载根目录了,而且必须只读.
有天酒后看“linux 安全”的书,顺手把 root 密码改了。
第二天醒来死活想不起来到底把密码改成什么,
只好乖乖跑到公司去接显示器 ~~~~
程序员很有乐趣!
想到前几天一悲催的事儿,我们部门的一老前辈了,据说以前还是什么中科院的研究生毕业,记得第一次是她叫我用tar给她打个.a的静态库。。。 第二次是她找一个可执行程序放到linux上说不能运行让我帮她把运行环境搞好,我上去file了那个可执行程序显示…RISC System/6000…后来才知道她老人家从AIX上ftp拷过来的。。。
1)软件的运行质量是远远大于代码质量的 ==> 就是这句话,我有感觉,但自己就是说不出来!
2)你的测试案例是远远小于生产环境的 ==> 可以理解,但经常忘记
3)软件的完美的质量,是靠长时间的运行、测试和错误堆出来的,而不是某种方法论 ==> 精辟!
我现在终于知道,自己写代码(给别人用)时的保守精神还远远不够啊!
1)软件的运行质量是远远大于代码质量的
2)你的测试案例是远远小于生产环境的
3)软件的完美的质量,是靠长时间的运行、测试和错误堆出来的,而不是某种方法论
这三句是最大的亮点。
但是点评者闹的最大笑话是第二个点评:
点评:这就是加班工作的恶果。另,在delete之前最好先做一次select。
其实一次 rollback 不就解决delete带来的问题了么?为什么不行?因为作者在此前的5小时操作之后没有commit,然后就直接开始做delete,所以rollback会导致他那5小时的事情重做。。。而此时离上线只有2小时。
所以第二个点评其实应该是:在长时间的操作完成后,一定要先commit一次再继续做后续操作。(这个点评不但适用于数据库,也适用于编程,花时间完成了一项伟大的壮举之后最好提交一次代码,免得此后搞砸。)