Назад | Перейти на главную страницу

Как определить, в каких процессах открыто больше всего индексных дескрипторов

Вот моя проблема, видимая в диаграмме Мунина:

Количество используемых / открытых инодов "внезапно" постоянно увеличивается.

Есть ли способ определить, какой процесс сохраняет самые открытые в данный момент inode? Я использовал подход https://unix.stackexchange.com/questions/117093/find-where-inodes-are-being-used и нашел и очистил некоторые папки с почтой и журналами, от которых я мог избавиться ... Тем не менее, если inodes ОТКРЫТЫ, должен быть какой-то процесс, поддерживающий их использование, верно? Это может не обязательно быть папка с наибольшим количеством файлов, из-за которой происходит увеличение - или я ошибаюсь?

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

Обновить

На основе сценария Эндрю я создал его версию, которая также показывает имя процесса. Поскольку у меня работает несколько процессов nginx / apache, которые могут возродиться, я хотел бы увидеть результаты по имени процесса.

for dir in /proc/*/fd;
do
    echo -n "$dir ";
    pid=`expr "$dir" : '\/proc\/\(.*\)\/.*'`; # extract the pid
    pname=`ps -p $pid -o comm=`; # grab process name
    echo -n "$pname ";
    ls $dir 2>/dev/null | wc -l;
done | sort -n -k 3

Пример вывода:

/proc/4612/fd sshd 49
/proc/46470/fd node 60
/proc/5655/fd nginx 66
/proc/6656/fd nginx 76
/proc/7654/fd nginx 81
/proc/8578/fd dovecot 107
/proc/9657/fd nginx 117
/proc/3495/fd java 146
/proc/4785/fd mysqld 382

Таким образом, следующий тест будет регистрировать распределение с течением времени, чтобы увидеть, какие изменения и как они соотносятся с количеством / proc / sys / fs / inode-nr, которое упомянул Морган.

Год спустя...

Прошло какое-то время, вот и новый график

И угадайте, в конце сентября произошла замена неисправного привода. Похоже, весь беспорядок возник из-за ошибки диска. Тем не менее, скрипты все равно пригодятся!

Подсчитайте количество записей в каждом /proc/[PID]/fd каталог. Это даст вам количество файловых дескрипторов, открытых каждым процессом. Хотя для перечисления всех процессов потребуется время, отсутствие процессов, которые запускаются или останавливаются во время вашего подсчета, не должно быть проблемой, поскольку вы ищете долгоживущий процесс с большим количеством открытых файловых дескрипторов.

Что-то вроде этого:

for dir in /proc/*/fd;
do
    echo -n "$dir "; #need a space to get real columns for the sort
    ls $dir 2>/dev/null | wc -l;
done | sort -n -k 2

В последних строках вывода будет показан каталог / proc / [PID] / fd с количеством дескрипторов открытых файлов для каждого процесса. Виновные процессы должны быть внизу.

Обратите внимание, что каждая запись в / proc / [PID] / fd технически является дескриптором файла, а не отдельным открытым индексным дескриптором, каждый отдельный открытый индексный дескриптор должен иметь как минимум один отдельный файловый дескриптор в каталоге / proc / [PID] / fd где-нибудь.

Я думаю, что проблема здесь отчасти в том, что munin подразумевает под "открытыми индексными дескрипторами". В моей стандартной установке munin есть два плагина для получения количества выделенных inodes:

"/ etc / munin / plugins / open_inodes", который получает метрику inode из "/ proc / sys / fs / inode-nr"

и

"/ etc / munin / plugins / df_inode", который получает метрику из вывода "df -i".

Эти числа отражают количество существующих файлов, а НЕ количество файлов / индексов, используемых всеми процессами в системе.

Например, этот скрипт создает десять файлов, и после его завершения мы можем увидеть увеличение распределения inode как в "df -i", так и в inode-nr.

    #!/usr/bin/python

    f0 = open("foo0", "w")
    f1 = open("foo1", "w")
    f2 = open("foo2", "w")
    f3 = open("foo3", "w")
    f4 = open("foo4", "w")
    f5 = open("foo5", "w")
    f6 = open("foo6", "w")
    f7 = open("foo7", "w")
    f8 = open("foo8", "w")
    f9 = open("foo9", "w")

Однако, если я настрою это, чтобы предотвратить завершение программы (а файлы уже существуют) ... файлы остаются «открытыми» и «используемыми» процессом.

    #!/usr/bin/python

    import time

    f0 = open("foo0", "w")
    f1 = open("foo1", "w")
    f2 = open("foo2", "w")
    f3 = open("foo3", "w")
    f4 = open("foo4", "w")
    f5 = open("foo5", "w")
    f6 = open("foo6", "w")
    f7 = open("foo7", "w")
    f8 = open("foo8", "w")
    f9 = open("foo9", "w")

    time.sleep(600)

что мы видим в выводе "lsof -p PID"

COMMAND    PID   USER   FD   TYPE DEVICE SIZE/OFF   NODE NAME
...
open_some 6602 morgan    3w   REG  254,1        0 262198 /home/morgan/src/foo0
open_some 6602 morgan    4w   REG  254,1        0 262273 /home/morgan/src/foo1
open_some 6602 morgan    5w   REG  254,1        0 262284 /home/morgan/src/foo2
open_some 6602 morgan    6w   REG  254,1        0 262287 /home/morgan/src/foo3
open_some 6602 morgan    7w   REG  254,1        0 262289 /home/morgan/src/foo4
open_some 6602 morgan    8w   REG  254,1        0 262301 /home/morgan/src/foo5
open_some 6602 morgan    9w   REG  254,1        0 262302 /home/morgan/src/foo6
open_some 6602 morgan   10w   REG  254,1        0 262309 /home/morgan/src/foo7
open_some 6602 morgan   11w   REG  254,1        0 262457 /home/morgan/src/foo8
open_some 6602 morgan   12w   REG  254,1        0 268672 /home/morgan/src/foo9

Но я могу запускать этот сценарий «открыть и оставаться открытым» столько раз, сколько захочу, и он не изменит числа в df / inode-nr.

Короче говоря, munin сообщает количество выделенных inodes, а не количество всех inodes, используемых всеми процессами. Если после того, как вы удалили кучу файлов, график munin не отражает свободные inodes, это может быть просто потому, что график не был повторно сгенерирован или, в показанном примере, шкала времени графика слишком длинная, чтобы отразить неожиданное изменение.

Возможно, если бы это было из-за файлов журнала, inodes не были выпущены, когда вы их очистили. Попробуйте либо перезапустить службы, в которых были открыты эти файлы журналов, либо вы сможете по-настоящему стереть файлы журналов без перезапуска, выполнив echo "" > logfilenamegoeshere после того, как вы создадите резервную копию любых данных, которые хотите сохранить из журнала.

Нашел утилиту "fatrace" для "трассировки доступа к файлам" от автора Сообщение блога доступно для скачивания Вот. Он отобразит все процессы, обращающиеся к любым файлам в системе.