程序员那些悲催的事儿
在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 ,请勿用于任何商业用途)
《程序员那些悲催的事儿》的相关评论
(1) i– ==》 n–
(2) i < N ==》 -i < N
(3) i < N ==》 i-N
@poet
是啊是啊,记得commit, 善用 rollback。。
alias rm=mv -t /home/del/
2个一口的哈哈·,睡觉
2个一口的连接在一起,AP?
虽然有些知识点我还看不懂,但是每看一篇文章都很有收获,谢谢。
我也曾经在我的笔记本上使用类似于这样的命令 rm -rf /tmp /, 但是就悲催了。。。
所以以后在使用rm的时候,每次打完命令后都不会马上按Enter,都要来回过几遍才敢按Enter!
受教了,感谢楼主分享,十分感谢。
我们组里5个人,每人都发生过 “delete from 表名 没加条件” 这事,而我,是第一个,后面四次每次发生这事后,都会开会,让我以身说法,讲讲要注意这件事。
好文章 受教了
RamDisk那个笑了,为了追求速度同样有过…
哈~~~還好我是菜鳥,所以我還沒有碰到過這麼多不幸哦!!不過我的版主呀~~關於其中有一個叫/dev/shm,這個東東要解說一下,它就是目前linux新的預設ramdisk(記憶快取硬碟),我是覺得新的啦!!因為我記得很久以前linux好像沒有預設這個東東,而是需要手動啟用才有的,不論對錯,請指教,謝謝。
如果是命令行执行delete/update table 可以接着写where限制然后退回去再写操作(eg: amount=amount+100),这样可以避免在没有输入限制条件下的错回车执行。
好文章啊!
赞
有一次给产品写个功能。但是不知道有个函数已经该。结果后台拼出来的sql是
DELETE FROM tablename WHERE array;
然后,然后还没有备份。。。
我最严重的一次问题是使用了未初始化变量,在之后的程序运行中灵异频发,最后花了5天时间调试这个bug。
对于此类灵异事件有同感,但我是在Java里重用集合变量而没有执行clear操作引起的·~~
@叉叉 我也犯过这个错误
很少发言。
但是今天看到博主能自己暴露自己的“丑”,勇气不是一般的大。佩服佩服。
突然想问博主个问题,如果博主面试的程序员实践经验很丰富,曾经设计了很多大型的线上正常运行很多年的系统,但是他理论知识差(套用曾经见过的“领导”的话说是,不是专业毕业的,说不出专业术语?),也有点不善表达。博主如何看待?
我是把 -rf 留在最后输入,避免放在前面当输入路径时误按到于是开始删除当前输入的路径。
现在的Linux下删除根都是保护的了
rm -r /
rm: cannot remove root directory `/’
@寂静的风之力
不信的是windows XP下面没有保护
如果在windows下面执行shell rm -fr /* 那你就重装系统吧
上次就被同事的shell干掉了
其实只要实现检查一下$dir是不是为空就可以了
第一份工作是在一个小公司。中国的小公司大家都知道,用的肯定是windows,而且1000%是盗版……
当时是02年,刚毕业,很热衷于追新(现在也差不多,不过比较能沉住气了)。
电脑上装的是win xp,已知打sp1补丁后不能装media player9,不然微软会锁硬盘——这事当年很出名。
可我就是想看看media player9有什么新东西啊……于是想,点下下载链接,不启动安装,只是看看what’s new应该没问题……
那天晚上刚好轮我值班。于是,找没密码的机器;拆硬盘挂第二硬盘——悲催的没数据线没电源线啊亲,这都配的什么破机器……
只好俩机箱并排放,手很困难的从两者直接的缝隙里伸进去,用我机器的电源和另一台机器的数据线,终于启动了……
可是,分区表死循环,一时又找不到磁盘工具,在这种磁盘上拷贝速度那个慢,和56K的小猫有得一拼……
折腾到3、4点才把我一个月的源码等关键资料拷出来,到6点多才把系统重装到勉强能工作,天已大亮了……
代码现在一般都会提交到SVN上吧
看了这个 突然发现 linux好强大啊
昨天,就在昨天,我向同事演示init q命令不能使inittab里面一行内容生效的时候,敲 init 然后转身把屏幕让给他看,随后敲了 q ,结果转身导致了我手位变化,敲在了1上,顺手就了,好在是测试环境
@Walkerinwind
说的不错啊,长了很多见识,免得自己亲身试错
恩,知耻而后勇,顶。
哈哈,/dev/shm/ 也发生在我身上过,不过那次好歹没对文件做多大改动。。也是“被重启”。。
从生产环境telnet,再telnet… 到了一个本机的测试环境虚拟机。通宵干完活,然后ctrl-d、ctrl-d… 然后init 0准备关机睡觉,结果发现关的是生产环境…………
这件事告诉我,不要T来T去、init 0前看看hostname… 还有尽量保持头脑清醒能力充足再去干活。
@调整自己 现在的面试更在乎你做过什么,而且最好能展示出来,我去公司笔试时交了白卷,真的一个字都没写,因为简历获得面试机会,通过了
sudo apt-get remove pythonX.X
结果整个Ubuntu崩盘
那是你没有加-rf选项 @寂静的风之力
delete import_table;
当时困得不行,删了以后立马清醒了。。。
看了楼主说的这些悲催事儿,我也说个自己的吧:
在测试代码的时候,总是烦在各个不同的角色之间做切换,于是呢想个自己添加个管理员权限,于是就有了如下的代码–
user = ClassName.find_by_username(‘dangel.ren’) //这个是我的用户在数据库中的记录,id=12811
is_admin = ********* && **** && **** || user.id = 12811 //这个是判断是否为管理员的bool变量
if (is_admin){}
改了之后,立马刷新,哈,自己就是管理员了,于是各种有权限的操作啊。
更厉害的是,我居然还把它fix到服务器上了,还好没有出什么大乱子。就是后来一个同事问我,怎么某个人不是管理员但是可以看到什么什么,于是我就debug了好长时间,最后终于在一个旮旯里发现了少写个“=”号啊
初学Linux,做了N多囧事,其一: rm -r * .swp 删除.swp文件,结果整个目录下没有文件了 请注意:*后边多一个空格
命令练习:cp -a /etc /tmp 紧接着来了次 rm -rf /etc 然后发现断网,桌面没有了,把/tmp下的CP回去,无效, 没有备份 然后,就没有然后了 这个命令太C了。
就不分享我自己的糗事了。
我觉得遵从pear coding standards 可以预防很多问题的发生:http://pear.php.net/manual/zh/standards.php
比如:
1. if ($var == ‘something’).. 改写作:if (‘something’ == $var )..
2. 尽量遵从 early return 原则
3. php文件后面不要放 ?>(简单、美观,避免header发送前意想不到的输出)
4. 多用include/require,少用include_once/require_once,并且用绝对路径去include(效率不同,并且APC缓存是根据绝对路径去缓存的)
5. php是弱类型的语言,但是有时候类型检查是必要的。
6. 有的变量用于拼凑sql的,记得在sql里面加上引号
“我把我的管理员口令提交到了一个开源软件的源码里。”
明明以前看过这篇文章,结果今天还是踩雷了:
https://github.com/shamiao/rpiwatch-www/commit/8717f26667701edc7a4abb8273347fd5218b443b