Script sao chép đĩa trên RPi

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

Comments Off on Script sao chép đĩa trên RPi

Filed under Software

Comments are closed.