Проверьте открытый предел FD для данного процесса в Linux


недавно у меня был процесс Linux, который "слил" файловые дескрипторы: он открыл их и не закрыл должным образом некоторые из них.

если бы я контролировал это, я мог бы сказать-заранее-что процесс достиг своего предела.

есть ли хороший, BashPython способ проверить коэффициент использования FD для данного процесса в системе Ubuntu Linux?

EDIT:

теперь я знаю, как проверить, сколько открытых файловых дескрипторов есть; я только нужно знать сколько дескрипторов файлов разрешено для процесса. Некоторые системы (например, Amazon EC2) не имеют .

спасибо,

Udi

7 53

7 ответов:

подсчитайте записи в /proc/<pid>/fd/. Жесткие и мягкие ограничения, применяемые к процессу, можно найти в /proc/<pid>/limits.

единственными интерфейсами, предоставляемыми ядром Linux для получения ограничений ресурсов, являются getrlimit() и /proc/pid/limits. getrlimit() можно получить только ограничения ресурсов вызывающего процесса. /proc/pid/limits позволяет получить ограничения ресурсов любого процесса с тем же идентификатором пользователя и доступен на RHEL 5.2, RHEL 4.7, Ubuntu 9.04 и любом дистрибутиве с ядром 2.6.24 или более поздней версии.

Если вам нужно поддержать старые системы Linux, то вам придется получить сам процесс, чтобы вызвать getrlimit(). Конечно, самый простой способ сделать это-изменить программу или библиотеку, которую она использует. Если вы используете программу, то вы можете использовать LD_PRELOAD загрузить свой код в программу. Если ни один из них не возможен, вы можете подключиться к процессу с помощью gdb и заставить его выполнить вызов в процессе. Вы также можете сделать то же самое с помощью ptrace() чтобы подключиться к процессу, вставьте вызовите в своей памяти, и т. д., однако это очень сложно получить право и не рекомендуется.

с соответствующими привилегиями другие способы сделать это будут включать просмотр памяти ядра, загрузку модуля ядра или иное изменение ядра, но я предполагаю, что об этом не может быть и речи.

вы можете попробовать написать скрипт, который периодически вызывает lsof -p {PID} на данный PID.

вы просили методы bash / python. ulimit был бы лучшим подходом к bash (за исключением munging through /proc/$pid/fd и тому подобное вручную). Для python можно использовать модуль ресурсов.

import resource

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

(1024, 65536)

resource.getrlimit соответствует getrlimit вызовите программу на языке C. Результаты представляют текущие и максимальные значения для запрошенного ресурса. В приведенном выше примере текущий (мягкий) предел составляет 1024. Значения являются типичными значениями по умолчанию Системы Linux в наши дни.

чтобы увидеть верхний 20 дескриптор файла с помощью процессов:

for x in `ps -eF| awk '{ print  }'`;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

вывод находится в формате file handle count, pid, cmndline для process

пример вывода

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

в CentOS 6 и ниже (все, что использует GCC 3), Вы можете обнаружить, что настройка ограничений ядра не решает проблему. Это потому, что есть FD_SETSIZE значение, которое устанавливается во время компиляции в использовании GCC. Для этого вам нужно будет увеличить значение, а затем повторно скомпилировать процесс.

кроме того, вы можете обнаружить, что вы утечка дескрипторов файлов из-за известные проблемы в libpthread Если вы используете эту библиотеку. Этот призыв был интегрирован в GCC в GCC 4 / CentOS7/RHEL 7, и это, похоже, исправило проблемы с потоками.

Python wrapper с использованием превосходного пакета psutil:

import psutil

for p in psutil.process_iter(attrs=['pid', 'name', 'username', 'num_fds']):
    try:
        soft, hard = p.rlimit(psutil.RLIMIT_NOFILE)
        cur = p.info['num_fds']
        usage = int(cur / soft * 100)
        print('{:>2d}% {}/{}/{}'.format(
            usage,
            p.info['pid'],
            p.info['username'],
            p.info['name'],
            ))
    except psutil.NoSuchProcess:
        pass