Вы можете сделать это с помощью awk
вот так:
awk '{for(i=1;i<=NF;i++)if($i=="sig[4]")print i}'
Это должно сработать для вас даже в случае нескольких записей.
Если вам нужны все числа на одной строке, вы можете заменить print
на printf
и настроить соответствующим образом.
Просто:
lsof | wc -l
сообщит вам количество файлов, открытых в системе.
Насколько эффективен этот код 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
Для выделенного балансировщика нагрузки я бы отслеживал общее количество файлов, открытых в системе, вместо того, чтобы тратить ресурсы ввода-вывода и ЦП на их подсчет по процессам. Оставшиеся открытые файлы нежелательными -процессами должны быть бессмысленным значением для предполагаемого результата.
Чтобы узнать глобальные открытые файлы системой Linux, нет необходимости их подсчитывать; ядро Linux отслеживает, сколько файлов у него открыто.
Чтобы это узнать, либо беги:
cat /proc/sys/fs/file-nr | awk ' { print $1 } '
или
sysctl fs.file-nr | awk ' { print $1 } '
Это намного эффективнее, чем подсчет всех файлов, открытых с выходом lsof
, который будет перемещаться по всем каталогам /proc/$PID/fd
и негативно повлияет на ресурсы ввода-вывода / ЦП вашей системы.