Nota: Esta pregunta se ha vuelto a solicitar con un resumen de todos los intentos de depuración here.Subproceso de Python. Error de error con OSError: [Errno 12] No se puede asignar memoria después del período de tiempo
Tengo un script de Python que se ejecuta como un proceso de fondo que se ejecuta cada 60 segundos. Parte de eso es una llamada al subprocess.Popen para obtener la salida de ps.
ps = subprocess.Popen(['ps', 'aux'], stdout=subprocess.PIPE).communicate()[0]
Después de correr durante unos días, la llamada se erroring con:
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
Sin embargo la salida del free en el servidor es:
$ free -m total used free shared buffers cached Mem: 894 345 549 0 0 0 -/+ buffers/cache: 345 549 Swap: 0 0 0
He buscado alrededor para el problema y encontró this article que dice:
La solución es para agregar más espacio de intercambio a su servidor. Cuando el núcleo se bifurca para iniciar el modelador o el proceso de descubrimiento, primero se asegura de que haya suficiente espacio disponible en el almacén de intercambio, si es necesario, del nuevo proceso.
Observo que no hay un intercambio disponible desde la salida gratuita anterior. ¿Es probable que este sea el problema y/o qué otras soluciones podría haber?
Actualización 13 de agosto de 09 El código anterior se llama cada 60 segundos como parte de una serie de funciones de supervisión. El proceso se demoniza y el control se programa usando sched. El código específico para la función anterior es:
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
Esto es parte de una clase más grandes llamados controles que se inicializa una vez cuando se inicia el demonio.
toda la clase cheques se puede encontrar en http://github.com/dmytton/sd-agent/blob/82f5ff9203e54d2adeee8cfed704d09e3f00e8eb/checks.py con la función GetProcesses definida a partir de la línea 442. Esto es llamado por doChecks() a partir de la línea 520.
Si ejecuta la parte superior, ¿ve que el proceso en segundo plano consume una mayor cantidad de memoria? Dado el código en el que falla, sospecho que me quedaré sin descriptores de archivo (aunque debería ser un error diferente). ¿Qué otro tipo de cosas haces cada 60 segundos? – bstpierre
Al haber registrado la salida de -m libre antes y después de cada llamada de Popen, la memoria permanece igual. ¿Cómo puedo verificar los descriptores de archivos? También se están lanzando varios otros procesos, pero también se están registrando y la memoria no se está "agotando" con el tiempo. – DavidM
Actualicé mi respuesta con otra sugerencia. –