如何在 Linux 中检查 USB 驱动器的物理健康状况?

如何在 Linux 中检查 USB 驱动器的物理健康状况?

如何检查 USB 驱动器的健康状态?

我如何知道 USB 坏了无法修复,还是可以修复?

答案1

没有办法查询 USB 记忆棒的 SMART 类参数;我不知道有任何记忆棒支持这样做,即使是通过公开的专有软件。您能做的最好的事情就是检查您是否可以使用 成功读取和写入整个设备badblocks

https://en.wikipedia.org/wiki/Badblocks

您想要指定其中一项写入测试,它将擦除记忆棒上的所有数据;请先进行备份。

dmesg插入 USB 后,通过查看来找到设备;您将看到设备名称(最有可能是,例如,等)和制造商信息。确保您使用的是正确的设备!sd<letter>sdcsdd

如果该记忆棒使用有效的文件系统格式化,您可能必须先将其卸载(使用命令 umount)。

示例语法,针对枚举为的 USB 记忆棒/dev/sdz,输出进度信息,带有数据破坏性写入测试并将错误日志写入 usbstick.log

sudo badblocks -w -s -o usbstick.log /dev/sdz

之后,您需要重新分区并重新格式化该记忆棒(假设它通过了);此测试将清除记忆棒上的所有内容。任何故障都表明设备的内存控制器出现故障,或者它已经用尽了备用块来重新映射故障块。在这种情况下,设备的任何区域都不可信任。

答案2

通过[ubuntu] 检查 USB 闪存盘错误,我最终发现了这一点,这可能会有所帮助:

我找到了 Fight Flash Fraud 和 SOSFakeFlash 博客,它们推荐使用软件 H2testw(参见此处或此处)来测试闪存。我下载了 H2testw,发现它有两个问题:(1)它仅适用于 Windows,(2)它不是开源的。但是,它的作者很好心地提供了一个文本文件来解释它的作用;此页面是关于我对该算法的 GPLv3 实现。
我的实现简单可靠,我不知道 F3 与 H2testw 相比究竟如何,因为我从未运行过 H2testw。我将我的实现称为 F3,即 Fight Flash Fraud 或 Fight Fake Flash 的缩写。

@pbhj 的补充:F3 在 Ubuntu 存储库中。它有两个部分,f3write 将 1GB 文件写入设备,f3read 随后尝试读取这些文件。这样可以测试容量以及写入和有效读取数据的能力。

答案3

我想这取决于故障模式。它们便宜是有原因的。

作为 USB 设备,通过 Windows 中的设备管理器观察总线或在 Linux 中通过 dmesg 的输出将告诉您该设备是否被识别为已插入。如果没有,则板上控制器或物理连接已断开。

如果设备被识别为已插入,但未被识别为磁盘控制器(我不知道这是怎么发生的,但是......)那么控制器就会被损坏。

如果它被识别为磁盘驱动器,但您无法安装它,您可能能够通过 fdisk 修复它并重写分区表,然后创建另一个文件系统。

如果你正在寻找聪明的,那么您将找不到它。拇指驱动器控制器很便宜。它们是商品存储,并不具备现代驱动器所具有的正常故障保护和智能。

答案4

许多故障要么是完全的,要么是允许一个位置支持多个位置。我编写了一个小型随机写入读取程序,该程序使用素数作为伪随机数生成器,用于模式和地址。读取在写入之后错开了足够的页面,以确保我没有在系统上测试 RAM 缓存。它尚未参数化,只是在我的系统上为具有 8G RAM 的 64G 设备设置。请随意批评、参数化,让它更智能。

这是一个强大的检查,比从下到上执行每个字节要快,但它也是一个很棒的交换生成器(几乎可以滚动出所有其他东西)。我暂时将 swapiness 设置为 1,它变慢了,但其他应用程序可以忍受。任何关于如何调整 swapout 的提示也将不胜感激:

$ sudo ksh -c'echo 1 > /proc/sys/vm/swappiness'

$ cat mysrc/test64g.c

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>

int main( int argc, char **argv ){

        long long int mask = 0xFFFFFFFF8L ;    // 64Gb word
        long long int stag = 8413257 ;  // 8G / 1021
        long long int inc = 1021L ;     // prime < 1024

        long long int w_addr = 0L ;
        long long int r_addr = 0L ;
        long long int w_ct = 0L ;
        long long int r_ct = 0L ;
        long long int w_patt = 0xFEDCBA9876543210L ;
        long long int r_patt = 0xFEDCBA9876543210L ;
        long long int r_buf ;
        int fd, ret ;

        if ( argc < 2
          || argv[1] == NULL
          || 0 > ( fd = open( argv[1], O_RDWR ))){
                printf( "Fatal: Cannot open file $1 for RW.\n" );
                exit( 1 );
        }

        while ( 1 ){
                if ( (off_t)-1 == lseek( fd, w_addr & mask, SEEK_SET )){
                        printf( "Seek to %llX\n", w_addr & mask );
                        perror( "Fatal: Seek failed" );
                        exit( 2 );
                }

                if ( 8 != ( ret = write( fd, (void*)&w_patt, 8 ))){
                        printf( "Seek to %llX\n", w_addr & mask );
                        perror( "Fatal: Write failed" );
                        exit( 3 );
                }

                w_ct++ ;
                w_addr += inc ;
                w_patt += inc ;

                if ( ( w_ct - r_ct ) < stag ){
                        continue ;
                }

                if ( (off_t)-1 == lseek( fd, r_addr & mask, SEEK_SET )){
                        printf( "Seek to %llX\n", r_addr & mask );
                        perror( "Fatal: Seek failed" );
                        exit( 4 );
                }

                if ( 8 != ( ret = read( fd, (void*)&r_buf, 8 ))){
                        printf( "Seek to %llX\n", w_addr & mask );
                        perror( "Fatal: Read failed" );
                        exit( 5 );
                }

                if ( ( ++r_ct & 0XFFFFF ) == 0 ){
                        printf( "Completed %lld writes, %lld reads.\n", w_ct, r_ct );
                }

                if ( r_buf != r_patt ){
                        printf( "Data miscompare on read # %lld at address %llX:\nWas: %llX\nS/B: %llX\n\n", r_ct, r_addr & mask, r_buf, r_patt );
                }

                r_addr += inc ;
                r_patt += inc ;
        }
}

相关内容