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은 개발 중인 커널 수준의 소프트웨어이므로 커널이 충돌하거나 정지될 가능성이 있습니다. 이런 경우는 드물지만 주의하세요.

인용하다

관련 정보