418개의 불량 섹터를 나열하는 mapfile
생성기가 있습니다 ddrescue
. 여기서 각 줄은 다음과 같습니다(빼기 기호는 불량 블록을 나타냄).
Position Size
0x1CC7C68000 0x00001000 -
debugfs
바이트 위치를 파티션 상대 섹터 번호로 변환함으로써 inode 번호를 쿼리한 다음 손상된 파일의 경로를 찾는 데 사용할 수 있습니다 . 불량 블록이 거의 2000개에 달하므로 이 작업을 수동으로 수행하는 것이 불가능하므로 이를 자동화하고 싶습니다. debugfs
파일 시스템에서 일련의 명령을 실행하는 스크립트를 작성할 수 있는 방법이 있습니까?
손상된 섹터의 파일 이름을 얻기 위해 현재 수행 중인 작업은 다음과 같습니다.
위치는
ddrescue
mapfile
디스크 시작 부분을 기준으로 바이트 단위입니다. 먼저 512로 나누어 위치를 섹터 번호로 변환한 다음 파티션의 시작 섹터 위치를 뺍니다.파티션의 첫 번째 섹터 : 91914240 불량 블록 위치 : 0x1CC7C68000 소수점 : 123610759168 절대 섹터 위치 : 123610759168 / 512 = 241427264 파티션의 상대 블록 위치 : 241427264-91914240 = 149513024
따라서 불량 섹터는 149513024
파티션 시작을 기준으로 합니다. debugfs
이제 다음을 사용하여 인덱스 노드를 찾을 수 있습니다.
$ debugfs
debugfs: open /dev/sdd3
debugfs: icheck 149513024
Block Inode number
149513024 1183169
debugfs: ncheck 1183169
Inode Pathname
1183169 /username/foo/bar/baz
debugfs
블록 위치 목록을 에 전달하고 해당 블록을 inode로 구문 분석하고 inode를 필터링하여 매핑되지 않은 inode를 제외시킨 다음 ncheck
경로 이름을 사용하여 나머지 inode를 구문 분석할 수 있도록 이 프로세스를 자동화하고 싶습니다 . debugfs와 일부 쉘 스크립트를 사용하여 이를 달성할 수 있습니까?
답변1
나는 내 문제에 대한 해결책을 찾았다고 믿습니다. 그러나 누군가가 더 우아한 솔루션을 생각해낼 수 있거나 내 솔루션에서 버그를 찾을 수 있는지 여전히 궁금합니다.
stdin에 쓸 수 있다는 것이 밝혀졌기 때문에 출력을 구문 분석할 수 있는 debugfs
일련의 명령을 생성하기만 하면 됩니다 .debugfs
ddrescue
다음 bash 스크립트는 이라는 mapfile.ddrescue
이름의 파일이 에 의해 생성된 현재 디렉터리에 존재한다고 가정합니다 ddrescue
.
for line in \
$(cat mapfile.ddrescue | \
grep -e "-$" | \
awk -F" " '{print $1}' | \
awk -F"0x" '{print $2}'); \
do \
position=$(( 16#$line / 512 - 91914240 )); \
result="$result $position"; \
done; \
echo -e "open /dev/sdd3\nicheck $result\nquit\n" | sudo debugfs
스크립트는 다음을 수행합니다.
- 나는
mapfile
내가 명명한 것을 분석했습니다.ddrescue
mapfile.ddrescue
- 하이픈으로 끝나는 줄만 유지하도록 필터링했습니다. 불량 블록이 있는 위치입니다.
- 저는 awk를 사용하여 공백을 분할하고 위치인 첫 번째 표시를 인쇄합니다. 여기에는 0x34A933F000과 같은 16진수 숫자가 포함됩니다.
Ox
접두사를 제거했습니다 .- 호출하는 사람이 반환한 결과는
$(...)
for 루프에 대한 입력으로 사용되므로 줄에는 항상 위치가 포함됩니다. - 저는
$(( ... ))
위치를 512(예: 섹터당 바이트 수)로 나누고 파티션 시작 위치(제 경우)를 빼는 표현식을 사용하여 위치에 대한 계산을 수행합니다91914240
. 이는 파티션 시작을 기준으로 섹터 위치를 제공합니다. - 각 위치를 공백으로 구분된 목록으로 연결하고
$result
. debugfs
마지막으로 sudo를 사용하여 실행되는 명령의 표준 입력 으로 파이프하는 줄바꿈으로 구분된 명령 목록을 생성합니다 . 이 명령은 장치를 엽니다(제 경우에는/dev/sdd3
). 그런 다음 에서icheck
실행$result
되고 종료됩니다debugfs
.
이 스크립트를 실행했을 때 이 블록의 모든 내용을 debugfs
찾는 데 오랜 시간이 걸렸습니다 inodes
. 제 경우에는 출력이 인쇄될 때까지 몇 분 동안 중단된 것처럼 보였습니다.
스크립트가 완료되면 결과를 텍스트 파일에 복사하여 분석합니다. 다행스럽게도 대부분의 섹터는 할당되지 않은 블록을 가리키고 나머지 섹터의 대부분은 동일한 소수의 숫자를 가리킵니다 inode
. 행을 삭제 <block not found>
하고 중복 항목을 제거한 후에는 수동 검사를 사용할 inodes
수 있는 행이 4개만 남습니다 . 그러면 이제 백업에서 복원하려고 시도할 파일인 4개의 파일 경로가 제공됩니다.debugfs
ncheck
배경
원래는 dd
256GB SSD의 내용을 더 큰 SSD에 복사하고 싶었습니다. dd
마지막 파티션의 약 45/185GB에서 I/O 오류로 인해 중단되었습니다. 하지만, ddrescue
저장할 수 있어요99.99%운전하다. 마지막으로 위의 해결 방법으로 남은 1700kb 즉 418개의 불량 섹터가 어떤 파일에 속하는지 확인할 수 있었고 4개의 파일만 손상되었음을 발견했습니다. 이제 어떤 파일이 손상되었는지 파악하고 이전 백업에서 해당 파일을 복원할 수 있으므로 데이터 복구에 대한 자신감이 크게 높아졌습니다.
답변2
내 rpi3b+ SD 카드가 죽은 후 오늘 이 작업을 수행해야 했습니다. 결국 파일 경로를 자동으로 표시한다는 점만 제외하고 위의 bash 스크립트에서 수행한 작업을 수행하는 Python 스크립트를 작성했습니다. 여기서 확인할 수 있습니다:https://github.com/zkrx/rescue2path
이 솔루션에서는 아직 스크랩되지 않은 데이터 덩어리("/")도 확인합니다. 여기서 오랫동안 면도를 하다가 끝나기 직전에 멈췄어요.
Arch wiki의 이 항목은 특히 유용합니다.https://wiki.archlinux.org/index.php/Identify_damaging_files