lsof:ソケットfdのI / O速度を測定します。

lsof:ソケットfdのI / O速度を測定します。

lsofソケットが開いているプロセスのリストを表示するために出力を解析するスクリプトを作成しています(表示されているものと似ていますnetstat)。lsofまた、ファイル記述子を提供しました。今私が望むのは、そのソケットを介してどれだけのデータ(KB /秒)が送信/受信されたかをスクリプトに伝えることです。

これまで私は以下を見てきました:

  1. nethogs:プロセスのネットワークI / Oを知らせますが、ソケットではなくプロセスごとにのみ通知します。
  2. iotop:プロセスごとのディスクI / Oを通知します。ネットワークI/Oとソケット別I/Oを区別する方法がないようです。
  3. /proc/pid/fd/:あまり意味がないようですね。
  4. fatrace:プロセスがアクセスするファイル(ソケットではない)を通知します。
  5. iostat:各ディスクの平均I / O統計を知らせます。
  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 -sread:各/呼び出しの結果を知らせます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は開発中のカーネルレベルのソフトウェアなので、カーネルがクラッシュしたり停止したりする可能性があります。このような場合はまれですが注意してください。

引用する

関連情報