今天不小心自己造了个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变量。