Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1215486
  • 博文数量: 122
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 4004
  • 用 户 组: 普通用户
  • 注册时间: 2014-02-20 08:27
文章分类
文章存档

2016年(1)

2015年(21)

2014年(100)

分类: LINUX

2014-07-18 11:42:44

在bash脚本中执行后台命令(加&)时,需要执行wait命令回收后台子进程的资源,否则会内存泄露?

最近遇到一个奇特的问题,在脚本中反复调用后台命令(后台命令执行后会退出),发现一段时间后,内存占用明显增加,有内存泄露的迹象。

经过深入分析,得出结论:
在脚本中,调用后台执行的命令,确实应该wait,不wait的话,确有内存泄露的情况,不信可以自己写个死循环调用后台命令的脚本,很容易复现的。
也可以google搜一下脚本多任务,可以看到别人写的类似的脚本中,有很多都是用了wait的。

通过内存泄露检测,和bash相关代码和原理分析,问题产生的原因简单如下:
1、实际的内存泄露并不是被调用的后台进程自身产生的,泄露之处在于bash,bash调用后台命令,后台命令执行结束后,自身占用的资源(包括内存)应 该是成功回收的(bash中应该考虑了SIGCHLD信号的处理),但问题关键在于:bash自己会为每一个后台子进程创建一个数据结构,用于保存后台进 程的返回值,否则bash中就无法了解后台子进程的退出状态了,这在一些情况下,确实是需要了解的。所以,泄露的内存就在这个数据结构上,如果不用 wait,那么每个后台子进程对应的数据结构就无法回收。
2、理论上,泄露的数据结构应该很小,不会产生大的影响,但是另一个关键在于glibc的堆实现,如果死循环中不断的创建后台子进程,那就不断的会有相应 的数据结构分配,而其占用的内存很可能顶在了堆顶,我们知道,如果堆顶的内存不能回收,那么堆顶之下的内存也是不能回收的,所以由于该数据结构的泄露,可 能导致更大的内存泄露。经过分析故障当时bash进程的堆分布情况,确实可以确认这一点。

综上,这个问题由于bash和glibc和脚本用法共同导致。
所以,各位,如果后面要在bash中调用后台命令,建议都wait一下吧。。。。

示例脚本:
内存泄露的脚本:

点击(此处)折叠或打开

  1. #!/bin/bash
  2. while true
  3. do
  4.     date &
  5.     sleep 1
  6.     echo "$(ps -eo cmd,rss|grep -v grep|grep 't.sh')"
  7. done
这个脚本运行后,可以明显看到内存有缓慢上升的情况。

内存不泄露的脚本:

点击(此处)折叠或打开

  1. #!/bin/bash
  2. while true
  3. do
  4.     date &
  5.     sleep 1
  6.     echo "$(ps -eo cmd,rss|grep -v grep|grep 't.sh')"
  7.     wait
  8. done
而这个脚本调用了wait,长时间运行,也不会有内存上升的情况。
阅读(3182) | 评论(0) | 转发(1) |
给主人留下些什么吧!~~