bash: สคริปต์แก้ Boot record ของ NTFS
update 2556-12-03
ลองใช้สคริปต์กับพาร์ติชั่นที่ขนาดไม่เท่ากันแล้วปรากฎว่าใช้ไม่ได้ เพราะ NTFS เก็บข้อมูลหลายอย่างมากกว่าแค่จุดเริ่มต้นและขนาด (ดูที่ NTFS Partition Boot Sector)
วิธีที่ได้ผลกว่าคือ ฟอร์แมตไดร์ฟไว้ก่อน -> เก็บ boot sector ไว้ 72 ไบต์ -> ทำ ntfsclone -> เอา boot recort ที่เก็บไว้มาเขียนทับ
ตัวอย่างเช่น จะคัดลอก ไดร์ฟ /dev/sda1 ไปยัง /dev/sdb1 ขั้นตอนจะเป็นดังนี้
$ sudo mkfs.ntfs -f /dev/sdb1 $ sudo dd if=/dev/sdb1 of=sdb1.img bs=72 count=1 $ sudo ntfsclone -O /dev/sdb1 /dev/sda1 $ sudo dd if=sdb1.img of=/dev/sdb1
*** สคริปต์ด้านล่างนี้ ล้าสมัยแล้ว ***
แก้ปัญหาเวลาใช้ ntfsclone ในการ restore พาร์ติชั่น NTFS มาลงในฮาร์ดดิสก์ลูกใหม่ ซึ่งจุดเริ่มต้นและขนาดอาจไม่เท่าของเดิม
วิธีการคือใช้ข้อมูลจากตาราง Master Boot Record ปัจจุบัน มาเขียนทับ boot record ของพาร์ติชั่น NTFS ที่ต้องการ โดยใช้เชลล์สคริปต์
$ vi ntfs_fix_boot_sector.sh
#!/bin/bash
function usage() {
cat <<EOF
Fix NTFS boot record:
Usage: $0 DEVICE
Example: $0 /dev/sda1
EOF
exit 1
}
if [ ! "$1" ]; then
usage
fi
PART=$1
if [ ! -b "$PART" ]; then
echo -e "$PART not found. Exit.\n"
usage
fi
BSF="`echo $PART | tr '/' '_'`.img"
BSFB=${BSF}.bak
BSFD="${BSF}_`date +%F`.bak"
function reverse_byte () { #reverse_byte HEXSTR
local S=$1 #HEXSTR
local B
local C
while [ "$S" ]; do
B=${S:(-2)}
S=${S:0:-2}
C="${C}\\x${B}"
done
echo $C
}
function replace_byte () { #replace_byte OFFSET LENGTH NUMBER
local O=$1 #OFFSET
local L=$2 #LENGTH
local N=$3 #NUMBER
let NL=${L}*2
XN=`printf "%0${NL}x" $N`
RXN=`reverse_byte $XN`
#echo "printf $RXN | dd of=$BSF bs=1 seek=$O count=$L conv=notrunc"
printf $RXN | sudo dd of=$BSF bs=1 seek=$O count=$L conv=notrunc > /dev/null 2>&1
}
sudo dd if=$PART of=$BSF bs=512 count=1 > /dev/null 2>&1
TMP="/tmp/$0_${RANDOM}.txt"
HDD=$PART
while [ "`echo ${HDD:(-1)} | tr '0123456789' ' '`" == " " ]; do
HDD=${HDD:0:-1}
done
sudo fdisk -l $HDD > $TMP
if ! cat $TMP | grep $PART | grep NTFS > /dev/null 2>&1; then
echo -e "$PART is not NTFS partition. Exit.\n"
sudo rm $TMP
sudo rm $BSF
usage
fi
if [ ! -f "$BSFB" ]; then
cp $BSF $BSFB
else
cp $BSF $BSFD
fi
echo "Fixing $PART ..."
HEADS=`cat $TMP | grep 'sectors/track' | cut -d, -f1 | cut -d\ -f1`
SECTORS=`cat $TMP | grep 'sectors/track' | cut -d, -f2 | cut -d\ -f2`
START=`cat $TMP | grep "${PART} " | awk -F' ' '{ print $2 }'`
END=`cat $TMP | grep "${PART} " | awk -F' ' '{ print $4 }'`
if [ "$START" == "*" ]; then
START=`cat $TMP | grep "${PART} " | awk -F' ' '{ print $3 }'`
END=`cat $TMP | grep "${PART} " | awk -F' ' '{ print $4 }'`
fi
let LENGTH=$END-$START
OFFSET_HEADS=26
OFFSET_SECTORS=24
OFFSET_START=28
OFFSET_LENGTH=40
LEN_HEADS=1
LEN_SECTORS=1
LEN_START=4
LEN_LENGTH=4
for i in HEADS SECTORS START LENGTH; do
A="OFFSET_${i}"
B="LEN_${i}"
replace_byte ${!A} ${!B} ${!i}
done
echo "Fix with heads=$HEADS, sectors/track=$SECTORS, start=$START, length=$LENGTH"
sudo dd if=$BSF of=$PART > /dev/null 2>&1
sudo rm $TMP
cat <<EOF
Command used:
sudo dd if=$BSF of=$PART
Revert with command:
sudo dd if=$BSFB of=$PART
EOF
ตัวอย่าง สมมุติว่าพาร์ติชั่นที่ต้องการเป็น /dev/sda1 คำสั่งคือ
$ ntfs_fix_boot_record.sh /dev/sda1
ได้ผลลัพธ์คือ
Fixing /dev/sda1 ... Fix with heads=255, sectors/track=63, start=2048, length=62914559 Command used: sudo dd if=_dev_sda1.img of=/dev/sda1 Revert with command: sudo dd if=_dev_sda1.img.bak of=/dev/sda1
ที่มา:
- Printer-friendly version
- Log in or register to post comments
- 7676 reads







Recent comments