lsof
ソケットが開いているプロセスのリストを表示するために出力を解析するスクリプトを作成しています(表示されているものと似ていますnetstat
)。lsof
また、ファイル記述子を提供しました。今私が望むのは、そのソケットを介してどれだけのデータ(KB /秒)が送信/受信されたかをスクリプトに伝えることです。
これまで私は以下を見てきました:
nethogs
:プロセスのネットワークI / Oを知らせますが、ソケットではなくプロセスごとにのみ通知します。iotop
:プロセスごとのディスクI / Oを通知します。ネットワークI/Oとソケット別I/Oを区別する方法がないようです。/proc/pid/fd/
:あまり意味がないようですね。fatrace
:プロセスがアクセスするファイル(ソケットではない)を通知します。iostat
:各ディスクの平均I / O統計を知らせます。tcpdump
:IPごとのすべてのトラフィックのダンプを提供します。トラフィックがどのソケットに属するかを知る方法がないようです。strace -p pid -e trace=network -s 0
:与えられたプロセスが特定のソケット関数を呼び出すたびに通知します。これは役に立つようですが、実際にはたくさんのものを提供しています。recvfrom(13, 0x7feed8fb3074, 4096, 0, 0, 0) = -1 EAGAIN (Resource temporarily unavailable)
strace -p pid -e trace=read,write -s
read
:各/呼び出しの結果を知らせますwrite
。
strace
有望に見えますが、正しくしているかどうかは確信できず(read,write
十分ですか?)オーバーヘッドが多く発生するようです。 (オープンソケットを持つ各プロセスに対してインスタンスを実行し、strace
出力を解析する必要があります。)
Linuxカーネルは、fd /ソケットごとにどれだけのI / Oが実行されるかを測定するためのより良い方法を提供しますか?iptables
何かが設定またはハッキングされる可能性がありますかnethogs
?
答え1
使用を検討してくださいシステムクリック。 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;
}
バニラ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は開発中のカーネルレベルのソフトウェアなので、カーネルがクラッシュしたり停止したりする可能性があります。このような場合はまれですが注意してください。
引用する
- https://sourceware.org/systemtap/- プロジェクトホームページ
- https://sourceware.org/systemtap/wiki- ウィキペディア
- https://sourceware.org/systemtap/tapsets/socket.stp.html- デモスクリプトで使用されているソケットタブセット
- https://sourceware.org/systemtap/langref/- SystemTap言語リファレンス