일부 프로세스에서 여전히 열린 파일을 삭제 한 경우 어떻게 복구합니까?


19
$ cat important_file > /dev/null &
[1] 9711
$ rm important_file 
$ killall -STOP cat

[1]+  Stopped                 cat important_file > /tmp/p
$ ls -l /proc/`pidof cat`/fd/
total 0
lrwx------ 1 vi vi 64 May 13 20:32 0 -> /dev/pts/29
l-wx------ 1 vi vi 64 May 13 20:32 1 -> /tmp/p
lrwx------ 1 vi vi 64 May 13 20:32 2 -> /dev/pts/29
lr-x------ 1 vi vi 64 May 13 20:32 3 -> /home/vi/important_file (deleted)

이것을 복구하는 방법 important_file?

나는 같은 것을 시도했다

injcode -m dup2 -ofd=3 -ofilename=/tmp/recovered_file -oflags=O_CREAT $PID_OF_CAT

그러나 그것은 아무것도하지 않습니다.

답변:


11

/ home이 NFS 인 경우 / home / vi에 액세스 / 복사 할 수있는 .nfsNNNNNNNNNN 파일이 있습니다. home이 로컬 파일 시스템 인 경우 / proc / PID / fd / 3 링크를 통해 동일한 작업을 수행 할 수 있어야합니다.

cp /proc/PID/fd/3 /tmp/recovered_file

실제로 파일 삭제를 취소 하려면 주제에 대한 블로그 게시물이 있습니다.


1
좋아, 나는 readlink /proc/13381/fd/3-> "/ home / vi / important_file (삭제됨)" 에 혼동되었고 /home/vi/important_file\ \(deleted\)분명히 존재하지 않습니다.
Vi.

22

... 주어진 시간에 복사하는 것 (그리고 파일 내용의 해당 시간의 스냅 샷 만 수집하는 것)보다 tail -f해당 파일을 새 파일로 " "하는 것이 좋습니다 .

tail -c +0 -f /proc/PIDofProgram>/fd/# > /new/path/to/file

(꼬리의 신중한 프로그래머 덕분에 바이너리 출력에서도 작동합니다.)

런타임 중에는 tail -f자체적으로 파일을 열어두고 원래 프로그램이 종료 될 때 디스크에서 파일을 제거하지 못하게합니다. 따라서, tail -f원래 프로그램이 끝난 직후에 바로 멈추지 마십시오. /new/path/to/file먼저 꼬리 원하는 것인지 먼저 확인하십시오 . 그렇지 않은 (또는 다른 이유로 불만족) 경우 다시 원본 파일을 복사 할 수 있지만,이 시간 이후에 그 모든 기록은 "프로그램"에 의해 끝나고에서 아직도 실행하고있다 tail -f'의 / proc 디렉토리 / PIDoftail / fd / 디렉토리.


3
/ proc / PIDofProgram> / fd / #에 대한 하드 링크를 만드는 것은 어떻습니까?
becko

2
@ 베코 Invalid cross-device link.
Kamil Maciorowski

10

lsof를 사용하여 inode 번호를 찾고 debugfs를 사용하여 하드 링크를 다시 작성하십시오. 예를 들면 다음과 같습니다.

# lsof -p 12345 | grep /var/log/messages
syslogd 12345 root    3w   REG                8,3    3000    987654 /var/log/messages (deleted)
# mount | grep var
/dev/sda2 on /var type ext3 (rw)
# debugfs -w /dev/sda2
debugfs: cd log
debugfs: ln <987654> tmp
debugfs: mi tmp
                      Mode    [0100600] 
                   User ID    [0] 
                  Group ID    [0] 
                      Size    [3181271] 
             Creation time    [1375916400] 
         Modification time    [1375916322] 
               Access time    [1375939901]
             Deletion time    [9601027] 0
                Link count    [0] 1
               Block count    [6232] 
                File flags    [0x0] 
...snip...
debugfs:  q
# mv /var/log/tmp /var/log/messages
# ls -al /var/log/messages
-rw------- 0 root root 3301 Aug  8 10:10 /var/log/messages

불만을 제기하기 전에 지금 삭제 할 파일이 없으므로 위의 사본을 위조했습니다. ;-)

mi삭제 시간과 링크 수를 적절한 값 (각각 0과 1)으로 재설정하는 데 사용 하지만 제대로 작동하지 않습니다. 링크 수가 0에 남아 있습니다 ls. 커널이 inode 데이터를 캐싱하고 있다고 생각합니다. 디버그를 사용한 후 가장 빠른 시간에 fsck를 사용해야 안전합니다.

내 경험상 임시 파일 이름을 사용하여 링크를 만든 다음 적절한 이름으로 바꾸어야합니다. 원본 파일 이름에 직접 연결하면 디렉토리가 손상 될 수 있습니다. YMMV!


실제로 제대로 작동하지 않고 시스템이 손상되는 경우 왜 정확하게 제안합니까? 나는 이것이 단순한 WiP이며 실제로 프로덕션에서 시도되어서는 안된다는 대답 내에서 더 생생한 면책 조항을 가져야한다고 생각합니다.
cnst

3

cp파일 만 가능 합니다.

cp /proc/<pid>/fd/<fdno> /new/path/to/file

물론 파일이 여전히 수정되는 경우이 접근 방식에 문제가 발생할 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.