2009-08-31 8 views
49

Recientemente tuve un proceso Linux que "filtró" descriptores de archivos: los abrió y no cerró correctamente algunos de ellos.Comprueba el límite FD abierto para un proceso determinado en Linux

Si hubiera monitoreado esto, podría decir con anticipación que el proceso estaba llegando a su límite.

¿Hay alguna manera agradable, Bash \ Python de verificar la relación de uso de FD para un proceso determinado en un sistema Ubuntu Linux?

EDIT:

ahora sé cómo comprobar el número de descriptores de archivos abiertos están allí; Solo necesito saber cuántos descriptores de archivos están permitidos para un proceso. Algunos sistemas (como Amazon EC2) no tienen el archivo /proc/pid/limits.

Gracias,

Udi

+0

¿Qué sistema operativo Amazon EC2 Linux está utilizando sin/proc/pid/limits? Está disponible en RHEL 5. Si desea una solución para un sistema operativo diferente, díganos cuál. – mark4o

+0

Tengo un servidor Ubuntu EC2, pero estoy interesado en una solución más general que se aplique a una amplia variedad de Linux Distros. –

Respuesta

94

Cuente las entradas en /proc/<pid>/fd/. Los límites duros y blandos que se aplican al proceso se pueden encontrar en /proc/<pid>/limits.

+0

Creo que este método puede ser más elegante que el sondeo lsof –

+0

Sí, pero algunos procesos, como los servidores web, piden una cuota más grande utilizando ulimit, y deseo monitorear su uso de FD. –

+3

No se permitirá que ningún proceso aumente su cuota por encima del límite, que se puede ver con 'ulimit -Hn'. – caf

2

Puede intentar escribir script que llame periódicamente lsof -p {PID} en su pid.

+0

lsof proporciona muchas entradas irrelevantes (como bibliotecas compartidas en la memoria). –

+1

Supongo que no importa si los fds están conectados a libs de memoria compartida o a archivos 'habituales' específicos de la aplicación, estos fds todavía usan su compartición. –

+0

No, esos no son descriptores de archivos abiertos y no cuentan para el límite del descriptor de archivos. – mark4o

2

Ha solicitado métodos bash/python. ulimit sería el mejor enfoque bash (corto de munging a través de /proc/$pid/fd y similares a mano). Para Python, puede usar el módulo de recursos.

import resource 

print(resource.getrlimit(resource.RLIMIT_NOFILE)) 
$ python test.py 

(1024, 65536) 

resource.getrlimit corresponde a la getrlimit llamada en un programa C. Los resultados representan los valores actuales y máximos para el recurso solicitado. En el ejemplo anterior, el límite actual (suave) es 1024. Los valores son valores predeterminados típicos en los sistemas Linux en estos días.

+0

resource.RLIMIT_NOFILE: El número máximo de descriptores de archivos abiertos para el proceso actual, y me gustaría obtener los resultados de OTRO proceso, no de mí mismo. –

31

Las únicas interfaces proporcionadas por el kernel de Linux para obtener los límites de recursos son getrlimit() y /proc/pid/limits. getrlimit() solo puede obtener los límites de recursos del proceso de llamada. /proc/pid/limits le permite obtener los límites de recursos de cualquier proceso con el mismo ID de usuario, y está disponible en RHEL 5.2, RHEL 4.7, Ubuntu 9.04 y cualquier distribución con kernel 2.6.24 o posterior.

Si necesita admitir sistemas Linux anteriores, deberá obtener el proceso para llamar al getrlimit(). Por supuesto, la forma más fácil de hacerlo es modificando el programa o la biblioteca que utiliza. Si está ejecutando el programa, puede usar LD_PRELOAD para cargar su propio código en el programa. Si ninguno de ellos es posible, entonces puede adjuntar al proceso con gdb y hacer que ejecute la llamada dentro del proceso. También puede hacer lo mismo utilizando el ptrace() para adjuntarlo al proceso, insertar la llamada en su memoria, etc., sin embargo, es muy complicado hacerlo bien y no es recomendable.

Con los privilegios adecuados, las otras formas de hacerlo serían mirar a través de la memoria del kernel, cargar un módulo kernel o modificar el kernel, pero supongo que están fuera de cuestión.

1

para ver las 20 de identificador de archivo superior usando procesos:

for x in `ps -eF| awk '{ print $2 }'`;do echo `ls /proc/$x/fd 2> /dev/null | wc -l` $x `cat /proc/$x/cmdline 2> /dev/null`;done | sort -n -r | head -n 20 

la salida es en el número de identificador archivo de formato, pid, cmndline para el proceso

ejemplo de salida

701 1216 /sbin/rsyslogd-n-c5 
169 11835 postgres: spaceuser spaceschema [local] idle 
164 13621 postgres: spaceuser spaceschema [local] idle 
161 13622 postgres: spaceuser spaceschema [local] idle 
161 13618 postgres: spaceuser spaceschema [local] idle 
0

En CentOS 6 y siguientes (cualquier cosa que use GCC 3), puede encontrar que ajustar los límites del kernel no resuelve el problema. Esto se debe a que hay un valor FD_SETSIZE que GCC establece en tiempo de compilación. Para esto, necesitará aumentar el valor y luego volver a compilar el proceso.

Además, es posible que tenga filtraciones de descriptores de archivos debido a known issues in libpthread si está utilizando esa biblioteca. Esta llamada se integró en GCC en GCC 4/CentOS7/RHEL 7 y esto parece haber solucionado los problemas de subprocesamiento.

Cuestiones relacionadas