LINUX GAZETTE
...리눅스를 좀 더 재미있게!
지워진 파일을 살린 경험담
By C.E.C. Artime and J.A. Baro

한글번역 전정호

이 글은 한글번역판입니다. 원문은 여기에서 볼 수 있습니다.

우리는 ext2 파일시스템에서 부주의하게 지워진 파일을 살린 시도를 적었다. 이런 일은 매우 끔찍하기때문에 여러분은 같은 실수를 하지말길 당부한다. 우리가 위기동안 배운 것들을 보여주기위해 우리는 상황 전체를 이야기하려 한다.

전주: 재난이 가져온

환경

하드웨어

Fish와 Bell이라는 두 컴퓨터. Fish는 Sun E250이고, Bell은 펜티엄3 (450 MHz)이다. 둘 모두 같은 이더넷 네트웍 안에 있다.

소프트웨어

Bell은 2.2r7에서 문제없이 업그레이드한 Debian GNU/Linux 3.0r0을 실행한다. 커널은 Linux 2.4.18 이다.

Fish도 Sparc64용 Debian 3.0r0 을 실행한다. 최근 2.2r7에서 업그레이드하고 보니 (root가 아닌) 일반 사용자가 XFree를 사용할 수 없는 문제가 발생했다. 커널은 Linux 2.4.18-SMP 이다.

모든 파일시스템은 ext2이다.

어떻게 망쳤나

Fish의 Xfree를 root는 사용할 수 있지만 일반 사용자는 사용할 수 없었다.
짐작: 권한이나 사용자 설정파일에 문제가 있다.
해결책: 새로운 사용자를 추가하여 홈디렉토리로 root의 (마침표로 시작하는) 설정파일을 복사한다:

root@fish# adduser judas
Enter new UNIX password:
Retype new UNIX password:
root@fish# cp --recursive /root/.[a-zA-Z]* /home/judas
root@fish# chown --recursive judas:judas /home/judas/.*

[cpchown의 정규표현식 아규먼트 사이의 차이를 발견했는가?]

많은 시도와 실수 끝에 X 문제를 해결했다. 이제 사용자를 제거한다.
과정을 조금 빠르게 하려고 시도하다가 manpage에서 매력적인 옵션을 발견했다:

root@fish# deluser --remove-all-files judas

차차차! 재난이 시작했다! 불행히도 이 옵션은 deluser가 디스크 전체에서 judas가 소유한 파일을 모두 지우게 만들었다!

/home이 다 사라졌다.
이분이 지난후 우리는 해당 장치를 (/dev/sda8) 언마운트(umount)했다.

백업

첫번째 시도

먼저 불운한 장치에 기록된 바이트를 그대로 복사하려고 했다.
Fish에 공간이 없어서, Bell의 하드디스크에 복사했다:

root@fish# ftp bell
ftp> put '|dd if=/dev/sda8' fishbackup

사실 이 과정은 네트웍에 문제가 있어서 이렇게 쉽지 않았다: 큰 파일을 전송하면 한참있다 끊어졌다. 파일을 나눠야 했다. 파티션 /dev/sda8의 크기는 10142 MiB이다.
GNU shellutilsfactor 도구를 사용했다:

root@fish# factor 10142
10142: 2 11 461

그래서 한 조각에 적합한 크기를 알 수 있다.

안전한 전송

다음으로 우리는 FTP대신 OpenSSL을 사용했다.
배치(batch)모드로 사용하기위해 먼저 암호를 교환했다:

root@fish# ssh-keygen 
artime@bell$ ssh-keygen
root@fish# scp /root/.ssh/identity.pub artime@bell:/home/artime/.ssh/authorized.keys
root@fish# scp artime@bell:~/.ssh/identity.pub ~/.ssh/authorized.keys

다음 스크립트를 Fish에서 실행했다:

#!/bin/sh
for i in $(seq 0 460)
do
  dd if=/dev/sda8 bs=$((2*11*1024)) skip=$i of=fula
  scp --batch fula artime@bell:~/fiback.$i
done

Bell에서 조각들을 붙였다:

for i in $(seq 0 460)
do cat fiback.$i >> fiback.raw
done

이 과정을 Fish에서 다음과 같이 한번에 할 수도 있다:

#!/bin/sh
for i in $(seq 0 460)
do
  dd if=/dev/sda8 bs=$((2*11*1024)) skip=$i | ssh artime@bell "cat >> fiback.raw"
done

잃어버린 자료 찾기

우리는 Aaron Crane이 쓴 Linux Ext2fs undeletion mini-HOWTO와 Tomas Ericsson이 쓴 Ext2fs undeletion of directory structures mini-HOWTO, Tom Pycke가 만든 recover 프로그램과 debugfs를 i386에서 사용하기위한 Torsten Werner의 패치에 매달렸다.

게으른 시도

Recover는 파일을 하나씩 살려내는 도구다. 우리는 파일을 갑자기 수백개 잃어버렸다. 그래서 이 도구는 좋은 선택이 아닌 것같다. 가장 직접적인 방법은 Werner의 debugfs 패치를 사용하는 것이다. 우리는 손상된 파일시스템의 복사본을 이미 i386에 저장했다. 그래서 우리는 twerner.debian.org에 있는 실행파일을 사용할 수 있다:

artime@bell$ ./debugfs fishback.raw
debugfs> restore
debugfs> quit
artime@bell$ mkdir mnt
artime@bell$ mount -t ext2 -o loop fishback.raw mnt
artime@bell$ ls -l mnt

우리는 이렇게 파일을 하나도 찾지못했다! 아마도 좀 늦게 /dev/sda8을 언마운트한 것같다. T. Werner가 홈페이지에 지적하듯이 그가 만든 도구는 아직 이름이 있는 파일만을 살릴 수 있다.

읽어볼 것들

Crane이 쓴 undeletion howto

The Linux Documentation Project에서 우리가 찾은 이 문서는 잃어버린 파일의 inode를 찾고 debugfsdump 명령을 사용하여 파일을 살리는 방법을 알려주었다. 그래서 같은 디렉토리의 많은 파일을 살릴 수 있었다. 그러나 이들은 지워진 전체 파일들의 작은 일부에 불과하다. 이미 말했듯이 이 HOWTO의 파일을 하나씩 살리는 방법은 우리에게 적합하지않다.

Ericsson이 쓴 directory undeletion howto

여기서 우리는 디렉토리안에서 지워진 파일들을 구별하는 방법을 알았다. 우리는 지시를 따랐다.
7절에 있는 스크립트를 우리의 debugfs에 맞도록 조금 수정했다

#!/bin/sh
awk '{ print "mi <" $1 ">\n"\
             "\n\n\n\n\n\n\n"\
             "0\n"\
             "1\n"\
             "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n" }'

어쨌든 우리는 디렉토리명을 찾지못해서 8절로 넘어가지 못했다. 그래서 다른 방법을 찾아야 했다.

Manpage

마지막 시도는

$ man debugfs

여기서 우리는 howto에 언급되지않은 rdump 명령어를 찾았다. Ext2fs Undeletion of Directory Structures mini-HOWTO 6절에서 얻은 lsdel.out에 기록된 디렉토리 inode로 다음 스크립트를 실행했다:

#!/bin/sh
awk '{ print "rdump <" $1 "> folders\n" }'

대부분의 디렉토리가 folders 디렉토리에 복구되었다. 그러나 이름이 없다! 그래서 마지막으로 우리는 내용을 보고 디렉토리 200개에 사용자이름을 붙였다. 그래도 몇몇 파일을, 특히 이메일 파일을 살리지 못했다. 직접 찾아보기로 했다:

$ strings fishback.raw | grep -B1 -A99 "To: lisistrata" > lisistrata.mbox

결말

우리가 더 다루고 싶은 것들.

RTFM

그리고 root로 처음부터 처음보는 옵션을 절대로 사용하지마라.

자기테입

Fish에는 자기테입장치가 있다. GNU mttar는 백업에 유용한 도구다. Aaron Crane이 쓴 howto에는 이와 관련한 흥미로운 링크들이 있다.

정규표현식

쉘 명령어에서 정규표현식을 사용하면, 특히 마침표로 시작하는 설정파일들을 다룰때 매우 위험하다. 아마도 root는 ("확장"이 아닌) 제한된 정규표현식을 지원하는 쉘을 사용해야 할 것이다. 우리는 esh을 고려하고 있다.

PDA

이 글은 대부분 (푸에르토리코) Gran Canaria 해변에서, 좀 유별난 자유소프트웨어 PDA인 Agenda VR3을 가지고 썼다.

 

[BIO] C.E.C. Artime은 2000년부터 GNU 팬이된 자유소프트웨어 옹호자다.

[BIO] J.A. Baro은 1996년부터 리눅스를 사용한 Perl 해커다.


Copyright © 2003, C.E.C. Artime and J.A. Baro. Copying license http://www.linuxgazette.com/copying.html
Published in Issue 86 of Linux Gazette, January 2003