
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