Dav*_*idM 10 python linux memory
注意:此问题已通过此处的所有调试尝试的摘要重新询问.
我有一个Python脚本作为后台进程运行,每60秒执行一次.部分原因是调用subprocess.Popen来获取ps的输出.
ps = subprocess.Popen(['ps', 'aux'], stdout=subprocess.PIPE).communicate()[0]
Run Code Online (Sandbox Code Playgroud)
运行几天后,调用错误:
File "/home/admin/sd-agent/checks.py", line 436, in getProcesses File "/usr/lib/python2.4/subprocess.py", line 533, in __init__ File "/usr/lib/python2.4/subprocess.py", line 835, in _get_handles OSError: [Errno 12] Cannot allocate memory
但是服务器上的free输出是:
$ free -m
total used free shared buffers cached
Mem: 894 345 549 0 0 0
-/+ buffers/cache: 345 549
Swap: 0 0 0
我一直在寻找这个问题,并发现这篇文章说:
解决方案是为服务器添加更多交换空间.当内核要求启动建模器或发现过程时,它首先确保交换存储上有足够的可用空间(如果需要).
我注意到上面的免费输出没有可用的交换.这可能是问题和/或可能存在的其他解决方案吗?
更新2009年8月13日上述代码每60秒调用一次,作为一系列监视功能的一部分.该进程是守护进程,并使用sched安排检查.上述功能的具体代码是:
def getProcesses(self):
self.checksLogger.debug('getProcesses: start')
# Memory logging (case 27152)
if self.agentConfig['debugMode'] and sys.platform == 'linux2':
mem = subprocess.Popen(['free', '-m'], stdout=subprocess.PIPE).communicate()[0]
self.checksLogger.debug('getProcesses: memory before Popen - ' + str(mem))
# Get output from ps
try:
self.checksLogger.debug('getProcesses: attempting Popen')
ps = subprocess.Popen(['ps', 'aux'], stdout=subprocess.PIPE).communicate()[0]
except Exception, e:
import traceback
self.checksLogger.error('getProcesses: exception = ' + traceback.format_exc())
return False
self.checksLogger.debug('getProcesses: Popen success, parsing')
# Memory logging (case 27152)
if self.agentConfig['debugMode'] and sys.platform == 'linux2':
mem = subprocess.Popen(['free', '-m'], stdout=subprocess.PIPE).communicate()[0]
self.checksLogger.debug('getProcesses: memory after Popen - ' + str(mem))
# Split out each process
processLines = ps.split('\n')
del processLines[0] # Removes the headers
processLines.pop() # Removes a trailing empty line
processes = []
self.checksLogger.debug('getProcesses: Popen success, parsing, looping')
for line in processLines:
line = line.split(None, 10)
processes.append(line)
self.checksLogger.debug('getProcesses: completed, returning')
return processes
Run Code Online (Sandbox Code Playgroud)
这是一个更大的类的一部分,称为检查,它在守护程序启动时初始化一次.
整个检查类可以在http://github.com/dmytton/sd-agent/blob/82f5ff9203e54d2adeee8cfed704d09e3f00e8eb/checks.py中找到,其中getProcesses函数是从442行定义的.这是由doChecks()从第520行开始调用的.
你可能有一个内存泄漏受到你的python脚本继承的一些资源限制(RLIMIT_DATA,RLIMIT_AS?)的限制.在运行脚本之前检查*ulimit(1)*s,并像其他人建议的那样分析脚本的内存使用情况.
ps在您向我们展示的代码段后,您如何处理变量? 你是否一直提到它,永远不会被释放?引用subprocess模块文档:
注意:读取的数据缓冲在内存中,因此如果数据大小很大或不受限制,请不要使用此方法.
...和ps aux在繁忙的系统上可能很冗长......
更新
您可以使用资源模块使用python脚本检查rlimits :
import resource
print resource.getrlimit(resource.RLIMIT_DATA) # => (soft_lim, hard_lim)
print resource.getrlimit(resource.RLIMIT_AS)
Run Code Online (Sandbox Code Playgroud)
如果这些返回"无限制" - (-1, -1)- 那么我的假设是不正确的,你可以继续前进!
另见resource.getrusage,尤其是 这些ru_??rss字段可以帮助您使用python脚本检测内存消耗,而不需要外部程序.
当你使用popen时,如果你希望它关闭额外的文件描述符,你需要提交close_fds=True。
创建一个新管道(发生在来自后台跟踪的 _get_handles 函数中)会创建 2 个文件描述符,但您当前的代码永远不会关闭它们,并且最终会达到系统最大 fd 限制。
不确定为什么您收到的错误表明内存不足:它应该是文件描述符错误,因为 的返回值pipe()具有此问题的错误代码。
| 归档时间: |
|
| 查看次数: |
22293 次 |
| 最近记录: |