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 언어 참조