预防Fork Bomb?

October 23, 2013

今天不小心自己造了个fork炸弹,然后引爆了…运气好用killall全杀了。

事情是这样的,今天想改进一下现在的用的command_not_found_handle,原来只显示程序名,现在想加上参数显示。然后我加了这么一句:

print "Can't run: %s\n" "$all"

注意我用了print而不是printf,因为没有print这个程序,所以又触发一次command_not_found_handle,然后就递归啦,建了大量的bash进程。

Fork炸弹最麻烦在于它可以让一个用户无法再建新进程,运气好的话,爆炸前就开了个shell,可以在里面用kill杀进程。其次就是会占用大量内存,也许在没到用户最大进程数就swap了,系统性能就大降了。

下面说的预防其实是指预防自己引爆Fork炸弹,如果系统都被人入侵了,能执行任意程序了,预防fork炸弹根本就没意义。

有人说用ulimit -u设置用户最大进程数,可以来预防fork炸弹。不过实际用处不大,只能说只能减少一点破坏。例如一个bash进程大约占3M的内存,设置太大一下就swap了,设置太小又可能影响正常使用,而且产生fork炸弹的不一定是bash,单靠用户进程数来限制是不够的。

也许在写代码的时候要注意一下会不会fork(),有fork()就先设ulimit再测试。推广一下就是测试前估计资源使用量,用ulimit设置限制再测试。

总的来说,资源管理是很麻烦的事。


PS. 随便重构了一下我的bash启动脚本,~/.bashrc里设置环境变量的都移到~/.bash_profile,现在~/.bashrc只用来执行其他脚本和设置shell变量。