注意:此问题已经重新提出,并附有所有调试尝试的摘要在此处。
我有一个Python脚本,作为后台进程每60秒执行一次。其中一部分是调用subprocess.Popen以获取ps的输出。
ps = subprocess.Popen(['ps', 'aux'], stdout=subprocess.PIPE).communicate()[0]
运行几天后,调用出现错误:
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
我已经搜索了该问题并找到了此文章,其中提到:
解决方案是为服务器添加更多的交换空间。当内核复制以启动模型或发现进程时,它首先确保在交换存储器中有足够的空间存储新进程(如果需要)。
我注意到,从上面的free输出中没有可用的交换。这可能是问题吗?还有哪些其他解决方案?
更新于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
这是更大的名为“检查”的类的一部分,该类在守护程序启动时初始化。
整个检查类可以在http://github.com/dmytton/sd-agent/blob/82f5ff9203e54d2adeee8cfed704d09e3f00e8eb/checks.py找到,其中getProcesses函数定义从442行开始。这由doChecks()在520行开始调用。