Примечание : этот вопрос был повторен с кратким изложением всех попыток отладки здесь .
У меня есть сценарий 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
Я искал проблему и нашел эту статью , в которой говорится:
Решение состоит в том, чтобы добавить больше пространства подкачки на ваш сервер. Когда ядро пытается запустить моделлер или процесс обнаружения, оно сначала обеспечивает достаточно места в хранилище подкачки для нового процесса, если это необходимо.
Хочу заметить, что в свободном выводе нет доступных свопов. Это может быть проблемой и / или какими могут быть другие решения?
Обновление 13 августа 09 Приведенный выше код вызывается каждые 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.