Эффективный мониторинг количества открытых FD на процесс?

Вы можете сделать это с помощью awk вот так:

awk '{for(i=1;i<=NF;i++)if($i=="sig[4]")print i}'

Это должно сработать для вас даже в случае нескольких записей.

Если вам нужны все числа на одной строке, вы можете заменить print на printf и настроить соответствующим образом.

4
18.05.2017, 20:56
3 ответа

Просто:

lsof | wc -l

сообщит вам количество файлов, открытых в системе.

0
27.01.2020, 21:01

Насколько эффективен этот код SystemTap для вашего варианта использования? Это не идеальное представление, поскольку оно отслеживает изменения только с момента его начала (поэтому все, что было открыто до начала, будет пропущено), и потребуется дополнительная работа, чтобы сделать вывод более разборчивым или подходящим.

global procfdcount

probe begin {
    printf("begin trace...\n\n")
}

probe syscall.open {
    procfdcount[pid()]++
}

probe syscall.close {
    p = pid()
    procfdcount[p]--
    if (procfdcount[p] < 0) {
        procfdcount[p] = 0
    }
}

probe kprocess.exit {
    p = pid()
    if (p in procfdcount) {
        delete procfdcount[p]
    }
}

probe timer.s(60) {
    foreach (p in procfdcount- limit 20) {
        printf("%d %lu\n", p, procfdcount[p])
    }
    printf("\n")
}

Запуск с помощью чего-то вроде:

... (install systemtap here) ...
# stap-prep
... (fix any reported systemtap issues here) ...
# stap procfdcount.stp

Недостатком этого метода является необходимость идентифицировать все "открытые файлы" (сокеты и т.д.), а затем корректировать количество с помощью соответствующих перехватчиков системных вызовов (если они доступны); вышеперечисленное отслеживает только файловые файлы. Другим вариантом может быть вызов task_open_file_handles для задач, которые попадают в ЦП, и периодически отображать самые последние из этих счетчиков.

global taskopenfh

probe begin {
    printf("begin trace...\n\n");
}

probe scheduler.cpu_on {
    p = pid();
    if (p == 0) next;
    taskopenfh[p] = task_open_file_handles(pid2task(p));
}

probe timer.s(60) {
    foreach (p in taskopenfh-) {
        printf("%d %lu\n", p, taskopenfh[p]);
    }
    delete taskopenfh;
    printf("\n");
}

При этом будет пропущено все, что не находится на ЦП; для полного списка потребуется полный обход процессов, а затем задач, хотя это может быть слишком медленно или слишком дорого, если у вас есть миллионы FD.

Кроме того, эти зонды не кажутся стабильными, так что, возможно, в будущем появится eBPF или что-то в этом роде? Например. второй на Centos 7 через некоторое время взрывается на

ERROR: read fault [man error::fault] at 0x0000000000000008 (((&(fs->fdt))))
near identifier 'task_open_file_handles' at
/usr/share/systemtap/tapset/linux/task.stp:602:10
0
27.01.2020, 21:01

Для выделенного балансировщика нагрузки я бы отслеживал общее количество файлов, открытых в системе, вместо того, чтобы тратить ресурсы ввода-вывода и ЦП на их подсчет по процессам. Оставшиеся открытые файлы нежелательными -процессами должны быть бессмысленным значением для предполагаемого результата.

Чтобы узнать глобальные открытые файлы системой Linux, нет необходимости их подсчитывать; ядро Linux отслеживает, сколько файлов у него открыто.

Чтобы это узнать, либо беги:

cat /proc/sys/fs/file-nr | awk ' { print $1 } '

или

sysctl fs.file-nr | awk ' { print $1 } '

Это намного эффективнее, чем подсчет всех файлов, открытых с выходом lsof, который будет перемещаться по всем каталогам /proc/$PID/fdи негативно повлияет на ресурсы ввода-вывода / ЦП вашей системы.

1
27.01.2020, 21:01

Теги

Похожие вопросы