Linux에서 열린 파일 수를 모니터링할 수 있기를 원합니다. 현재 /proc/<pid>/fd
합계의 파일 수를 계산하고 있습니다 fdinfo
.
내 로드 밸런서에는 약 백만 개의 FD가 있습니다. 따라서 실행하는 데 약 20초가 걸립니다.
그러나 이로 인해 CPU 사용량이 높아집니다.47.18% [kernel] [k] __d_lookup
이 번호를 얻는 더 효율적인 방법이 있나요?
답변1
전용 로드 밸런서의 경우 I/O 및 CPU 리소스를 프로세스별로 계산하여 낭비하는 대신 시스템에서 열려 있는 총 파일 수를 추적합니다. 원치 않는 프로세스의 나머지 열린 파일은 예상 결과에 대해 의미 없는 값을 가져야 합니다.
Linux 시스템에서 전역적으로 열린 파일 수를 확인하려면 통계가 필요하지 않습니다. Linux 커널은 열려 있는 파일 수를 추적합니다.
이를 확인하려면 다음을 실행하세요.
cat /proc/sys/fs/file-nr | awk ' { print $1 } '
또는
sysctl fs.file-nr | awk ' { print $1 } '
이는 출력을 사용하여 열린 모든 파일을 계산하는 것보다 훨씬 더 효율적입니다. lsof
이는 모든 /proc/$PID/fd
디렉터리를 통과하고 시스템 I/O/CPU 리소스에 부정적인 영향을 미칩니다.
답변2
단순한:
lsof | wc -l
시스템에 열려 있는 파일 수를 알려줍니다.
답변3
귀하의 사용 사례에 대해 이 SystemTap 코드가 얼마나 효율적입니까? 이는 시작부터 변경 사항만 추적하므로(따라서 시작 전에 열린 모든 항목은 누락됨) 출력을 더 명확하거나 더 적절하게 만들기 위해 추가 작업이 필요하므로 완벽한 보기는 아닙니다.
global procfdcount
probe begin {
printf("begin trace...\n\n")
}
probe syscall.open {
procfdcount[pid()]++
}
probe syscall.close {
p = pid()
procfdcount[p]--
if (procfdcount[p] < 0) {
procfdcount[p] = 0
}
}
probe kprocess.exit {
p = pid()
if (p in procfdcount) {
delete procfdcount[p]
}
}
probe timer.s(60) {
foreach (p in procfdcount- limit 20) {
printf("%d %lu\n", p, procfdcount[p])
}
printf("\n")
}
비슷한 방식으로 실행합니다.
... (install systemtap here) ...
# stap-prep
... (fix any reported systemtap issues here) ...
# stap procfdcount.stp
이 접근 방식의 단점은 모든 "열린 파일"(소켓 등)을 식별한 다음 적절한 시스템 호출 후크(사용 가능한 경우)를 통해 개수를 조정해야 한다는 것입니다. 위의 방법은 파일 파일만 추적합니다. 또 다른 옵션은 task_open_file_handles
작업을 CPU로 호출 하고 주기적으로 최신 개수를 표시하는 것입니다.
global taskopenfh
probe begin {
printf("begin trace...\n\n");
}
probe scheduler.cpu_on {
p = pid();
if (p == 0) next;
taskopenfh[p] = task_open_file_handles(pid2task(p));
}
probe timer.s(60) {
foreach (p in taskopenfh-) {
printf("%d %lu\n", p, taskopenfh[p]);
}
delete taskopenfh;
printf("\n");
}
그러나 이는 CPU에 없는 모든 것을 놓치게 됩니다. 전체 목록에는 완전한 프로세스와 작업이 필요하지만 수백만 개의 FD가 있는 경우 너무 느리거나 비용이 많이 들 수 있습니다.
또한 프로브가 불안정해 보이는데 앞으로 eBPF나 다른 것이 사용될 수도 있을까요? 예를 들어 Centos 7의 두 번째 것은 얼마 후 폭발했습니다.
ERROR: read fault [man error::fault] at 0x0000000000000008 (((&(fs->fdt))))
near identifier 'task_open_file_handles' at
/usr/share/systemtap/tapset/linux/task.stp:602:10