Việc sao chép đĩa trên RPi bằng lệnh dd có thể bị lỗi I/O nếu dùng cổng USB 3.0 hay block size lớn (thí dụ bs=4M).
Script này kiểm tra đĩa trước/sau khi chép để tránh lỗi.
Có thể sao chép đĩa từ file ảnh vào SD card hay ngược lại, hoặc sao chép từ đĩa vào đĩa.Tất cả cấu trúc đĩa, data và cả phần đĩa trống sẽ được sao chép.
# Script disktool, version 20191021 # Kiểm tra/Sao chép đĩa # © 2019 LNT <lnt@ly-le.info> # #!/bin/bash function usage(){ cat >&2 <<EOF usage: $(basename $0) options -i nguồn: sao chép từ nguồn=(disk|file) -o đích: sao chép tới đích=(disk|file|folder) -c đĩa: kiểm tra đĩa=(disk|file) EOF exit 2 } function checkdsk(){ dsk="$1" if [[ -f "$dsk" ]]; then dsk=`sudo losetup -Pf --show $dsk` || usage else [[ -z "$dsk" ]] && usage [[ ${dsk:0:5} != '/dev/' ]] && dsk="/dev/$dsk" [[ ! -b $dsk ]] && usage fi echo -e "\nKiểm tra đĩa: $dsk" lst=`sudo fsck -N ${dsk}* | cut -s -d' ' -f5- | sed "/^$/d;\:${dsk} $:d"` while read chk part; do echo "*** $part" mounted=$(blkid -o device | grep $part) if [[ $mounted ]]; then sudo umount $part &> /dev/null || continue fi sudo $chk -fy $part || continue [[ $mounted ]] && sudo mount $part &> /dev/null done <<< $lst [[ -f "$dsk" ]] && sudo losetup -d $dsk &> /dev/null } function copydsk() { src="$1" dst="$2" if [[ ! -f "$src" ]]; then [[ -z "$src" ]] && usage [[ ${src:0:5} != '/dev/' ]] && src="/dev/$src" [[ ! -b $src ]] && usage fi if [[ ! -f "$dst" ]]; then [[ -z "$dst" ]] && usage if [[ -d "$dst" ]]; then dst=${dst}/$(date '+%Y-%m-%d').img else [[ ${dst:0:5} != '/dev/' ]] && dst="/dev/$dst" [[ ! -b $dst ]] && usage fi fi [[ -b $src ]] && checkdsk $src pkname=${dst:5} while read part; do sudo umount $part done <<< $(lsblk -ln -o name,pkname | sed "\_ ${pkname}$"'_!d;s_\(\S*\).*$_/dev/\1_') echo -e "\nSao chép đĩa: $src --▸ $dst" sudo dd if="$src" of="$dst" bs=1M status=progress >&2 || exit 2 if [[ -b $dst ]]; then sudo sync $dst checkdsk $dst fi } unset ACT SRC TAR while getopts 'c:i:o:' c do case $c in c) ACT=chk;SRC=$OPTARG ;; i) ACT=dd; SRC=$OPTARG ;; o) ACT=dd; TAR=$OPTARG ;; esac done case $ACT in chk) SECONDS=0 checkdsk $SRC duration=$SECONDS echo -e "\nHoàn thành kiểm tra đĩa trong $(( $duration / 60 )) phút $(( $duration % 60 )) giây" ;; dd) SECONDS=0 copydsk $SRC $TAR duration=$SECONDS echo -e "\nHoàn thành sao chép đĩa trong $(( $duration / 60 )) phút $(( $duration % 60 )) giây" ;; *) usage ;; esac