열려 있지만 삭제 된 큰 파일 찾기 및 제거


120

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

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

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

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


2
pid를 알고 있다면 lsof -p <pid>열린 파일과 크기를 나열 하는 데 사용할 수 있습니다 . 삭제 된 파일 (deleted)옆에 파일이 있습니다 . 삭제 된 파일이 연결될 /proc/<pid>/fd/1것입니다. 프로세스가 종료하지 않고 파일 설명자에 쓰는 것을 중지시키는 방법을 모르겠습니다. 나는 그것이 프로세스에 달려 있다고 생각합니다.
donothingsuccessfully

감사. rm여전히 열려있는 모든 ed 파일 의 PID를 어떻게 얻을 수 있습니까?
dotancohen

@donothingsuccessfully lsof가보고 한 "삭제 된"태그는 Solaris마다 다르며 실제로는 Solaris 10 이상입니다. OP는 사용중인 운영 체제를 지정하지 않았습니다. @dotancohen Solaris에서 lsof의 출력을 파이프하여 삭제 된 항목을 검색 할 수 있습니다 (예 :) lsof | grep "(deleted)". 삭제 된 파일을 열어 놓은 프로세스가 더 이상 없으면 커널은 inode 및 디스크 블록을 비 웁니다. 프로세스에는 "핸들러"가 없으므로 열려있는 기본적으로 잠긴 파일이 디스크에서 제거되었음을 알릴 수 있습니다.
Johan

2
@Johan, lsof | grep '(deleted)'Linux에서도 작동합니다. Linux에서는 inotify 메커니즘 (IN_DELETE_SELF 이벤트)을 사용하여 파일 삭제 (더 이상 / proc / some-pid / fd 이외의 디렉토리에 항목이없는 파일도 포함)를 통지 할 수 있습니다.
Stéphane Chazelas

나는 somefile그것을 VIM에서 만들고 연 다음 rm다른 배쉬 프로세스에서 ed했다. 그런 다음 lsof | grep somefile파일이 VIM에서 열려 있어도 실행 되고 거기에 없습니다.
dotancohen

답변:


141

애플리케이션을 종료 할 수없는 경우 공간을 확보하기 위해 로그 파일을 삭제하는 대신 잘라낼 수 있습니다. 파일이 추가 모드 ( 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", ....)입니다.


1
truncate동일한 작업을보다 명쾌하게 수행 하는 명령 도 있습니다 .
Tobu

1
@dotancohen Stephane은 pid를 알 수 없을 때이를 수행하는 방법에 대한 정보를 포함하도록 편집했습니다.
Didi Kohen

1
@OlivierDulac lsof은 아마도 열려있는 파일을 나열 할 수있는 휴대용 솔루션에 가장 가까운 것일 것입니다. 응용 프로그램 피트 아래에서 fd를 닫는 디버거 접근 방식도 이식성이 뛰어납니다.
Stéphane Chazelas

2
@StephaneChazelas : 감사합니다. : 나는 각 파티션에 열려있는 파일이있는 모든 PID를 나열하는 방법을 발견 df -k | awk 'NR>1 { print $NF }' | xargs fuser -Vud 합니다 (FD를 공개하도록 강제로 범죄자에 신호를 보낼 수있는 쉬운 다음 등)
올리비에 Dulac

6
을 사용할 수도 있습니다 lsof +L1. lsof 매뉴얼 페이지에서 : "양식 +L1지정은 +aL1 <file_system>링크 해제 된 열린 파일을 선택 합니다. 양식 지정은 지정된 파일 시스템에서 링크 해제 된 열린 파일을 선택합니다." 그것은 grepping보다 조금 더 안정적이어야합니다.
Synchro

31

빠른 시작을 확인하십시오 : 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

1

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

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

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


2
Linux는 대부분의 파일 시스템에서 스파 스 파일 을 지원하므로 동작이 잘 정의되어 있으며 디스크 드라이버가 실제로 디스크 공간을 확보 할 수 있습니다. ext3 및 ext4에 대해 테스트했으며 Stephane이 작성한 것처럼 작동합니다.
jofel

1
파일을 자르더라도 미리 할당 된 블록이 재생되지 않는다고 말하는 이유는 무엇입니까? 잘라내 기는 데이터 할당을 해제하기위한 것이며, 그에 대한 모호함은 없습니다.
Stéphane Chazelas

1
파일 시스템은 특히 파일이 잘 리기 전에 충분히 큰 경우 나중에 시간을 절약하기 위해 할당 된 블록을 유지합니다 (특히 파일이 여전히 열려있는 경우). 적어도 그것이 XFS가하는 것 같습니다.
peterph

피터 감사합니다. 이 게시물에서 "이유"를 설명하게되어 기쁩니다.
dotancohen

2
내가 알 수있는 한 열린 파일을 자르면 XFS의 공간도 회수됩니다. fallocateLinux 4.9에서 일반 파일과 파일이 모두 할당 된 상태 에서 테스트되었습니다 . 파일을 자르면 공간을 확보하지 못하는 파일 시스템 및 조건을 명확히 설명 할 수 있습니까?
Stéphane Chazelas
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.