I made a script to verify every sector on an sdcard as there are a lot of low quality ones in ciurculation.
A lot of tools just surface read the drive. I wanted a tool to write to every sector and hash verify the whole of the card.
Others will just read and write individual sectors. Due to wear leveling you wouldn't necessarily know which sectors were being written to.
You would need to fill the drive completely with random data and then verify as a whole to ensure all sectors are valid.
Due to the wonders of chatgpt, I made my tool that works for this job.
** It will format the card, you will have to confirm and by default it won't run without a force switch if the drive is more than 128GB.
./verifysdcard.sh /dev/sdX
A lot of tools just surface read the drive. I wanted a tool to write to every sector and hash verify the whole of the card.
Others will just read and write individual sectors. Due to wear leveling you wouldn't necessarily know which sectors were being written to.
You would need to fill the drive completely with random data and then verify as a whole to ensure all sectors are valid.
Due to the wonders of chatgpt, I made my tool that works for this job.
** It will format the card, you will have to confirm and by default it won't run without a force switch if the drive is more than 128GB.
./verifysdcard.sh /dev/sdX
Code:
#!/bin/bash# Function to unmount all partitions of a deviceunmount_partitions() { echo "Unmounting all partitions on $SDCARD..." for partition in $(lsblk -lnp "$SDCARD" | awk '{print $1}'); do echo "Unmounting $partition..." sudo umount -l "$partition" 2>/dev/null || true sudo fuser -k "$partition" 2>/dev/null || true done echo "All partitions unmounted."}# Function to format the device as a single ext4 partitionformat_sdcard() { echo "WARNING: This will format $SDCARD ..." read -p "Are you sure you want to proceed? (y/n): " CONFIRM if [[ "$CONFIRM" != "y" ]]; then echo "Formatting canceled." exit 1 fi # Unmount existing partitions first unmount_partitions echo "Creating new partition table on $SDCARD..." sudo parted -s "$SDCARD" mklabel gpt || { echo "Failed to create GPT partition table."; exit 1; } sudo parted -s "$SDCARD" mkpart primary ext4 1MiB 100% || { echo "Failed to create ext4 partition."; exit 1; } # Force kernel to re-read the partition table sudo partprobe "$SDCARD" sleep 2 # small delay to let auto-mounters do their thing # Just in case the system auto-mounted the newly created partition: sudo umount -l "${SDCARD}1" 2>/dev/null || true sudo fuser -k "${SDCARD}1" 2>/dev/null || true echo "Formatting ${SDCARD}1 to ext4..." sudo mkfs.ext4 -F "${SDCARD}1" || { echo "Failed to format partition as ext4."; exit 1; } echo "Formatting complete."}# Mount the first partition (e.g., /dev/sdg1)mount_partition() { PARTITION="${SDCARD}1" MOUNT_POINT="/mnt/sdcard" mkdir -p "$MOUNT_POINT" echo "Mounting partition $PARTITION..." sudo mount "$PARTITION" "$MOUNT_POINT" || { echo "Failed to mount $PARTITION. Please check the partition setup."; exit 1; }}# Function to check device sizecheck_device_size() { local device_size_bytes device_size_bytes=$(sudo blockdev --getsize64 "$SDCARD") local max_size_bytes=$((129 * 1024 * 1024 * 1024)) # 129GB in bytes if [[ "$device_size_bytes" -ge "$max_size_bytes" ]]; then if [[ "$FORCE" != true ]]; then echo "ERROR: The device $SDCARD is larger than 129GB." echo "Use the --force switch to override this check." exit 1 else echo "WARNING: Overriding size check for device $SDCARD (larger than 129GB)." fi else echo "Device size check passed: $SDCARD is less than 129GB." fi}# Check if `pv` is installed. If not, install it automaticallyif ! command -v pv &>/dev/null; then echo "pv is not installed. Installing now..." sudo apt-get update && sudo apt-get install -y pv if ! command -v pv &>/dev/null; then echo "ERROR: Failed to install pv. Exiting." exit 1 fifi# Check for required argumentsif [ "$#" -lt 1 ]; then echo "Usage: $0 [--force] [--size <size>] /dev/sdX" echo " --force: Optional. Override the size limit check (129GB)." echo " --size: Optional. Specify a custom size for testing (e.g., 500MB)." exit 1fi# Parse argumentsFORCE=falseCUSTOM_SIZE=0while [[ "$1" == --* ]]; do case "$1" in --force) FORCE=true ;; --size) shift CUSTOM_SIZE=$(echo "$1" | awk '/[0-9]+[KMG]/ { unit = substr($0, length($0), 1); size = substr($0, 1, length($0)-1); if (unit == "K") { print size * 1024; } else if (unit == "M") { print size * 1024 * 1024; } else if (unit == "G") { print size * 1024 * 1024 * 1024; } }') ;; *) echo "Unknown option: $1" && exit 1 ;; esac shiftdoneSDCARD="$1"LOCAL_COPY="/tmp/sdcardcheck"# Validate the SD card sizecheck_device_size# Always format the SD cardformat_sdcard# Mount the first partition (e.g., /dev/sdg1)PARTITION="${SDCARD}1"MOUNT_POINT="/mnt/sdcard"mkdir -p "$MOUNT_POINT"sudo mount "$PARTITION" "$MOUNT_POINT" || { echo "Failed to mount $PARTITION"; exit 1; }# Function to get available space on the SD card in bytesget_available_space() { df --output=avail "$MOUNT_POINT" | tail -n 1 | awk '{print $1 * 1024}'}# Determine the amount of data to writeif [[ $CUSTOM_SIZE -gt 0 ]]; then WRITE_SIZE=$CUSTOM_SIZE echo "Using custom size: $((WRITE_SIZE / 1024 / 1024)) MB."else WRITE_SIZE=$(get_available_space) echo "Available space on SD card: $((WRITE_SIZE / 1024 / 1024)) MB."fiBLOCK_SIZE=$((1024 * 1024)) # 1 MBBLOCK_COUNT=$((WRITE_SIZE / BLOCK_SIZE))if [[ $BLOCK_COUNT -le 0 ]]; then echo "ERROR: No space available or invalid custom size specified." exit 1fi# Generate random data, write to both SD card and local copyecho -e "\nWriting random data to local file..."dd if=/dev/urandom iflag=fullblock of="$LOCAL_COPY" bs=$BLOCK_SIZE count=$BLOCK_COUNT status=progress# 2) Copy the local file to the SD cardecho -e "\nWriting random data to SD Card file..."pv -p -t -e -r "$LOCAL_COPY" > "$MOUNT_POINT/largefile"# Wait for all writes to completeecho -e "\nSyncing..."sync# Calculate MD5 hash for the local copyecho -e "\nCalculating MD5 for local copy..."LOCAL_HASH=$(pv -p -t -e -r -s "$(stat -c '%s' "$LOCAL_COPY")" "$LOCAL_COPY" | md5sum | awk '{print $1}')# Calculate MD5 hash for the SD card fileecho -e "\nCalculating MD5 for SD card file..."SDCARD_HASH=$(pv -p -t -e -r -s "$(stat -c '%s' "$MOUNT_POINT/largefile")" "$MOUNT_POINT/largefile" | md5sum | awk '{print $1}')# Compare hashesif [ "$LOCAL_HASH" == "$SDCARD_HASH" ]; then echo -e "\nSUCCESS: Hashes match. Data integrity verified.\n" rm -f "$LOCAL_COPY" # Remove the local copyelse echo -e "\nERROR: Hashes do not match. Data integrity check failed." echo "Local Hash: $LOCAL_HASH" echo "SD Card Hash: $SDCARD_HASH"fi# Clean upsudo umount "$MOUNT_POINT"rm -rf "$MOUNT_POINT"Statistics: Posted by primetechguides — Thu Jan 16, 2025 12:02 pm — Replies 7 — Views 160