열려 있지만 삭제 된 큰 파일 찾기 및 제거 어떻게 그러한 파일을 제거 할

삭제되었지만 응용 프로그램에서 여전히 열려있는 큰 파일은 어떻게 찾습니까? 프로세스에서 파일을 열었더라도 어떻게 그러한 파일을 제거 할 수 있습니까?

상황은 로그 파일을 엄청난 속도로 채우는 프로세스를 실행하는 것입니다. 이유를 알고 있으며 수정할 수 있습니다. 그때까지 프로세스를 종료하지 않고 로그 파일을 rm 또는 비우고 싶습니다.

단순히 수행 rm output.log하면 파일에 대한 참조 만 제거되지만 프로세스가 종료 될 때까지 디스크의 공간을 계속 차지합니다. 더 나쁜 것은 : rming 후 파일의 위치 또는 크기를 알 수있는 방법이 없습니다! 파일이 다른 프로세스에서 여전히 열려 있어도 파일을 찾고 비울 수있는 방법이 있습니까?

특히 Debian 또는 RHEL과 같은 Linux 기반 운영 체제를 말합니다.



답변

애플리케이션을 종료 할 수없는 경우 공간을 확보하기 위해 로그 파일을 삭제하는 대신 잘라낼 수 있습니다. 파일이 추가 모드 ( O_APPEND)로 열려 있지 않은 경우 다음 번에 응용 프로그램이 파일을 쓸 때 파일 크기가 커지지 만 (앞부분이 희박하고 NUL 바이트가 포함 된 것처럼 보이지만) 회수됩니다 (이는 스파 스 파일을 지원하지 않는 Apple OS / X의 HFS + 파일 시스템에는 적용되지 않음).

자르려면 :

: > /path/to/the/file.log

Linux에서 이미 삭제 된 경우 다음을 수행하여 계속 잘라낼 수 있습니다.

: > "/proc/$pid/fd/$fd"

$pid파일을 연 프로세스의 프로세스 ID와 $fd파일 디스크립터가있는 하나의 파일 디스크립터 는 어디에 있습니까 lsof -p "$pid"?

pid를 모르고 삭제 된 파일을 찾고 있다면 다음을 수행 할 수 있습니다.

lsof -nP | grep '(deleted)'

lsof -nP +L1, @ user75021에서 언급 한 바와 같이 (미만 1 개 링크가 목록 파일) 더 나은 (더 안정적이고 더 휴대용) 옵션입니다.

또는 (Linux) :

find /proc/*/fd -ls | grep  '(deleted)'

또는 다음을 사용하여 큰 것을 찾으십시오 zsh.

ls -ld /proc/*/fd/*(-.LM+1l0)

대안으로 응용 프로그램이 동적으로 연결되어 있으면 디버거를 연결 close(fd)하고 new를 호출 하는 것 open("the-file", ....)입니다.


답변

빠른 시작을 확인하십시오 : lsof빠른 시작

lsof 빠른 시작 파일 (lsof에 포함)을 언급 한 사람이 아무도 없습니다. “3.a”섹션은 열려 있고 링크되지 않은 파일을 찾는 방법을 보여줍니다.

lsof -a +L1 *mountpoint*

예 :

[root@enterprise ~]# lsof -a +L1 /tmp
COMMAND   PID   USER   FD   TYPE DEVICE    SIZE NLINK  NODE NAME
httpd    2357 apache   29u   REG 253,17 3926560     0  1499 /tmp/.NSPR-AFM-3457-9820130.0 (deleted)
mysqld   2588  mysql    4u   REG 253,17      52     0  1495 /tmp/ibY0cXCd (deleted)
mysqld   2588  mysql    5u   REG 253,17    1048     0  1496 /tmp/ibOrELhG (deleted)
mysqld   2588  mysql    6u   REG 253,17       0     0  1497 /tmp/ibmDFAW8 (deleted)
mysqld   2588  mysql    7u   REG 253,17       0     0 11387 /tmp/ib2CSACB (deleted)
mysqld   2588  mysql   11u   REG 253,17       0     0 11388 /tmp/ibQpoZ94 (deleted)
httpd    3457   root   29u   REG 253,17 3926560     0  1499 /tmp/.NSPR-AFM-3457-9820130.0 (deleted)
httpd    8437 apache   29u   REG 253,17 3926560     0  1499 /tmp/.NSPR-AFM-3457-9820130.0 (deleted)
httpd    8438 apache   29u   REG 253,17 3926560     0  1499 /tmp/.NSPR-AFM-3457-9820130.0 (deleted)
httpd    8439 apache   29u   REG 253,17 3926560     0  1499 /tmp/.NSPR-AFM-3457-9820130.0 (deleted)
httpd    8440 apache   29u   REG 253,17 3926560     0  1499 /tmp/.NSPR-AFM-3457-9820130.0 (deleted)
httpd    8441 apache   29u   REG 253,17 3926560     0  1499 /tmp/.NSPR-AFM-3457-9820130.0 (deleted)
httpd    8442 apache   29u   REG 253,17 3926560     0  1499 /tmp/.NSPR-AFM-3457-9820130.0 (deleted)
httpd    8443 apache   29u   REG 253,17 3926560     0  1499 /tmp/.NSPR-AFM-3457-9820130.0 (deleted)
httpd    8444 apache   29u   REG 253,17 3926560     0  1499 /tmp/.NSPR-AFM-3457-9820130.0 (deleted)
httpd   16990 apache   29u   REG 253,17 3926560     0  1499 /tmp/.NSPR-AFM-3457-9820130.0 (deleted)
httpd   19595 apache   29u   REG 253,17 3926560     0  1499 /tmp/.NSPR-AFM-3457-9820130.0 (deleted)
httpd   27495 apache   29u   REG 253,17 3926560     0  1499 /tmp/.NSPR-AFM-3457-9820130.0 (deleted)
httpd   28142 apache   29u   REG 253,17 3926560     0  1499 /tmp/.NSPR-AFM-3457-9820130.0 (deleted)
httpd   31478 apache   29u   REG 253,17 3926560     0  1499 /tmp/.NSPR-AFM-3457-9820130.0 (deleted)

Red Hat 시스템에서 빠른 시작 파일의 로컬 사본을 찾으려면 일반적으로 다음과 같이합니다.

[root@enterprise ~]# locate -i quickstart |grep lsof
/usr/share/doc/lsof-4.78/00QUICKSTART

… 아니면 이거:

[root@enterprise ~]# rpm -qd lsof
/usr/share/doc/lsof-4.78/00.README.FIRST
/usr/share/doc/lsof-4.78/00CREDITS
/usr/share/doc/lsof-4.78/00DCACHE
/usr/share/doc/lsof-4.78/00DIALECTS
/usr/share/doc/lsof-4.78/00DIST
/usr/share/doc/lsof-4.78/00FAQ
/usr/share/doc/lsof-4.78/00LSOF-L
/usr/share/doc/lsof-4.78/00MANIFEST
/usr/share/doc/lsof-4.78/00PORTING
/usr/share/doc/lsof-4.78/00QUICKSTART
/usr/share/doc/lsof-4.78/00README
/usr/share/doc/lsof-4.78/00TEST
/usr/share/doc/lsof-4.78/00XCONFIG
/usr/share/man/man8/lsof.8.gz

답변

실제로 할 파일 시스템 드라이버에 달려 무료 할당 된 공간을, 그것은 보통 한 번 일어날 모든 해당 파일을 참조 파일 기술자가 해제됩니다. 따라서 응용 프로그램에서 파일을 닫지 않으면 공간을 실제로 회수 할 수 없습니다. 즉, 파일을 종료하거나 디버거에서 “비트”로 재생하는 것을 의미합니다 (예 : 파일을 닫고 다시 열거 나 쓰지 않도록하거나 /dev/null대신 열지 않음). 아니면 커널을 해킹 할 수도 있지만 그에 반대하는 것이 좋습니다.

Stephane이 제안한대로 파일을 자르면 도움이 될 수 있지만 실제 결과는 파일 시스템에 따라 달라집니다 (예를 들어 사전 할당 된 블록은 파일을 닫은 후에 만 ​​해제 될 수 있음).

이 동작의 근거는 커널이 그러한 파일을 대상으로하는 데이터 요청 (읽기 및 쓰기, 읽기는 실제로 더 중요)으로 무엇을해야하는지 알 수 없다는 것입니다.