lsof: измерять скорость ввода-вывода сокета fd

Я пишу скрипт, который анализирует вывод lsof чтобы показать список процессов, в которых открываются сокеты (как показано в netstat ). lsof также дает мне файловый дескриптор. Теперь я хочу, чтобы мой скрипт также указывал, сколько данных (в КБ / сек) отправляется / принимается через этот сокет.

До сих пор я смотрел:

  1. nethogs : Сообщает мне о сетевом nethogs / выводе процесса, но только для каждого процесса, а не для каждого сокета.
  2. iotop : сообщает мне диск ввода-вывода за процесс; как представляется, не в состоянии рассказать сетевой ввод-вывод и ввод-вывод на сокет.
  3. /proc/pid/fd/ : Не похоже, что это может мне многое сказать.
  4. fatrace : Сообщает мне, какие файлы (не сокеты) обрабатываются процессом.
  5. iostat : Сообщает мне среднюю статистику ввода-вывода на диск.
  6. tcpdump : дает мне свалку всего трафика на IP; похоже, не может определить, к какому сокету принадлежит трафик.
  7. strace -p pid -e trace=network -s 0 : Сообщает мне каждый раз, когда данный процесс вызывает определенные функции сокетов, что кажется полезным, но на практике это только дает мне много recvfrom(13, 0x7feed8fb3074, 4096, 0, 0, 0) = -1 EAGAIN (Resource temporarily unavailable)
  8. strace -p pid -e trace=read,write -s : Сообщает мне результат каждого вызова read / write .

strace выглядит многообещающе, но я не уверен, что правильно его работаю ( read,write достаточно?), плюс кажется, что будет много накладных расходов. (Для каждого процесса с открытым соке я должен был бы запустить экземпляр strace и проанализировать вывод.)

Является ли ядро ​​Linux более удобным средством для измерения количества операций ввода-вывода на fd / socket? Возможно, что-то можно настроить с помощью iptables или взломать nethogs ?

Рассмотрите возможность использования SystemTap . Это клон DTrace, но для Linux – он компилирует модуль ядра, который динамически исправляет ядро ​​и имеет полный доступ к его данным (поэтому в этом lsof может не понадобиться).

Тем не менее, больше информации, которую вы задаете, станет более сложным и специфичным для ядра версией сценария.

Например, простая стат-утилита для сокетов будет выглядеть так:

 global stats; probe begin { printf("%14s %6s %12s %5s %5s %8s\n", "NAME", "PID", "EXECNAME", "INO", "OPS/S", "BYTES"); } function file_ino:long (file:long) { if(file == 0) return -1; d_inode = @cast(file, "file", "kernel")->f_inode; if (d_inode == 0) return -1; return @cast(d_inode, "inode", "kernel")->i_ino; } probe socket.send, socket.receive { if(success == 0) next; /* Get inode number for a socket. Depending on operation, struct file is contained in different fields. Determine that field and get inode number */ ino = -1; if(@defined($sock)) { ino = file_ino($sock->file); } else if(@defined($iocb)) { ino = file_ino($iocb->ki_filp); } stats[pid(), execname(), ino, name] <<< size; } probe timer.s(1) { /* Every 1 second print statistics */ foreach([pid+, ename, ino, name] in stats) { printf("%14s %6d %12s %5d %5d %8d\n", name, pid, ename, ino, @count(stats[pid, ename, ino, name]), @sum(stats[pid, ename, ino, name])); } delete stats; } 

Я тестировал его на vanilla Linux 3.12, но, как вы видите, логика получения числа inode зависит от внутренней структуры ядра.

Как вы можете видеть, большую часть времени он прослеживает себя на сеансе SSH:

  NAME PID EXECNAME INO OPS/S BYTES socket.send 2655 sshd 7480 1 96 socket.send 2655 sshd 7480 1 96 socket.send 2655 sshd 7480 1 96 ... 

В примерах существует гораздо более сложный сценарий: https://sourceware.org/systemtap/examples/network/socktop

Предупреждение

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

Рекомендации