如何知道/ dev / sdX是连接的USB还是HDD?


23

我怎么知道 /dev/sdX是本地硬盘还是USB闪存盘?我更希望在没有root特权的情况下执行此操作。

好, udevadm帮了很多忙:

对于本地硬盘:

udevadm info --query=all --name=sdb | grep ID_BUS
E: ID_BUS=ata

对于USB密钥:

udevadm info --query=all --name=sdc | grep ID_BUS
E: ID_BUS=usb

Answers:


15

有几种方法可以在没有root特权的情况下进行判断,其中许多都是棘手的/ hacky的:

使用/dev/disk/by-id

find /dev/disk/by-id/ -lname '*sdX'

如果此响应类似/dev/disk/by-id/usb-blah-blah-blah,则为USB磁盘。其他前缀包括atadmmemstickscsi,等。

使用/dev/disk/by-path没有明显不同:

find /dev/disk/by-path/ -lname '*sdX'

你会得到类似的东西/dev/disk/by-path/pci-0000:00:1d.7-usb-0:1:1.0-scsi-0:0:0:0。这显示了通往磁盘的设备路径。在这种情况下,粗略路径是PCI→USB→磁盘。(请注意-usb-)。

使用的udev(我运行Debian的我,udevadm/sbin这不是我的$PATH-你可以在别的地方,开启或关闭您的$PATH):

/sbin/udevadm info --query=all --name=sdX | grep ID_BUS

您将获得设备所在的总线类型。删除以| grep ID_BUS获得完整的信息列表(您可能需要添加|less)。

如果已lshw安装,则惠更斯的答案也可能有效:

lshw -class disk -class storage | less

并查看您的磁盘的输出。在中less,尝试/sdX并看前面的几行bus info-第一行只是说一遍,但是前面scsi@…的几行会更有启发性。但是,您实际上应该以超级用户身份运行它,因此它可能不合适。(症状:在我尝试过的笔记本电脑上,它列出了SATA磁盘,但没有sudo列出USB磁盘-同时列出了两者)

还有其他一些,或多或少比这些直接。


是否有办法区分内部SATA驱动器与连接的外部SATA驱动器esatap
CMCDragonkai

10

我知道一个解决方案,但可悲的是,它需要root特权。无论如何,您可能仍然觉得它有用:

sudo lshw -class disk -class storage

对于每个设备,它将打印逻辑名称(例如/dev/sda)和总线信息,如果是USB设备,则将类似于“ usb @ 1:2”。

样本输出:

[...]
  *-storage
       description: SATA controller
       physical id: d
       bus info: pci@0000:00:0d.0
       configuration: driver=ahci latency=64
[...]
     *-disk:0
          description: ATA Disk
          physical id: 0
          bus info: scsi@2:0.0.0
          logical name: /dev/sda
[...]
  *-scsi
       physical id: 3
       bus info: usb@1:2
       configuration: driver=usb-storage
     *-disk
          description: SCSI Disk
          physical id: 0.0.0
          bus info: scsi@6:0.0.0
          logical name: /dev/sdc
[...]

8

您可以使用lsblk

lsblk -do名称,tran
NAME TRAN
sda  sata
sdb  sata
sdd  usb

其中-d--nodeps表示不打印从属设备,-o name,tran或或--output name,tran仅列出设备名称和设备传输类型。添加rm到输出列列表中,以查看可移动的设备(1如果true):

lsblk --nodeps-输出NAME,TRAN,RM
NAME TRAN   RM
sda  sata    0
sdb  sata    0
sdd  usb     1

我一直在寻找答案
Eduard Florinescu

4

这不需要root特权(但是许多命令使用并依赖bashisms,因此它们在所有POSIX兼容的shell中都无法使用):

有一种快速的方法来询问:sdX

grep -H . /sys/block/sda/{capability,uevent,removable,device/{model,type,vendor,uevent}}
/sys/block/sda/capability:52
/sys/block/sda/uevent:MAJOR=8
/sys/block/sda/uevent:MINOR=0
/sys/block/sda/uevent:DEVNAME=sda
/sys/block/sda/uevent:DEVTYPE=disk
/sys/block/sda/removable:0
/sys/block/sda/device/model:WDC WD360GD-00FN
/sys/block/sda/device/type:0
/sys/block/sda/device/vendor:ATA     
/sys/block/sda/device/uevent:DEVTYPE=scsi_device
/sys/block/sda/device/uevent:DRIVER=sd
/sys/block/sda/device/uevent:MODALIAS=scsi:t-0x00

真正有趣的文件capability。在我的Debian上,我有一个genhd.h文件,因此:

eval $(sed -ne '
   s/#define.*GENHD_FL_\([A-Z0-9_]*\)[ \t]*\([0-9]*\) \?.*$/GENHD_FLAGS[\2]="\1"/p
  ' /usr/src/linux-headers-2.6.32-5-common-openvz/include/linux/genhd.h)
diskCapa=$(</sys/block/sda/capability)
for i in ${!GENHD_FLAGS[@]};do
    (( diskCapa & i )) && echo ${GENHD_FLAGS[i]}
  done
MEDIA_CHANGE_NOTIFY
UP
SUPPRESS_PARTITION_INFO

diskCapa=$(</sys/block/sdd/capability)
    for i in ${!GENHD_FLAGS[@]};do
    (( diskCapa & i )) && echo ${GENHD_FLAGS[i]}
  done
REMOVABLE
MEDIA_CHANGE_NOTIFY
UP
SUPPRESS_PARTITION_INFO

完全只知道是否removable设置了标志:

grep REMOVABL /usr/src/linux-headers-3.2.0-4-common/include/linux/genhd.h 
#define GENHD_FL_REMOVABLE                      1

所以

for disk in sd{a,b,c,d,e,f,g,h} ; do
 (( $(< /sys/block/$disk/capability ) & 1 ))  &&  echo $disk is removable
done

通过测试capability值(在sda上面的示例中为52 )是否具有1设置位(即,是否为奇数)来工作。

但是Linux会在中渲染所有标志/sys,因此要求/sys/block/sdX/removable简单得多!;-)

因此,一个USB密钥可能是removable,但也有大量的移动设备,我宁愿以确保尺寸介质的大于0(如空载的CD-ROM托盘,样品) 设备不是在使用:在观看时sdX/trace/enable不受约束:

注意:所有这些都在bash v4.2 +上经过了很好的测试。

,您可以使用这种快速有效的方法:

for disk in /sys/block/* ; do
    [ -f "$disk/removable" ]    && [ $(<"$disk/removable") -gt 0 ]   &&
    [ -f "$disk/size" ]         && [ $(<"$disk/size") -gt 0 ]        &&
    [ -f "$disk/trace/enable" ] && [ -z "$(<"$disk/trace/enable")" ] &&
    echo "${disk##*/} $(($(<"$disk/size")/1953125))G $(<"$disk/device/model")"
  done

在我的系统上,有4个USB密钥,但是其中一个(sde)已安装,因此上一个命令输出:

sdd 8G Trans-It Drive
sdf 7G Storage Media
sdg 4G silicon-power

我的剧本:

我写了一点函数来安装升级的Debian Live。

#!/bin/bash

txtsize() {
    local _c=$1 _i=0 _a=(b K M G T P)
    while [ ${#_c} -gt 3 ] ; do
        ((_i++))
        _c=$((_c>>10))
      done
    _c=000$(( ( $1*1000 ) >> ( 10*_i ) ))
    ((_i+=${3:-0}))
    printf -v ${2:-REPLY} "%.2f%s" ${_c:0:${#_c}-3}.${_c:${#_c}-3} ${_a[_i]}
}

#第一部分仅呈现人类可读的大小。该功能从此处开始。

chooseFreeUsbKey() {
    local _lUdisk _lUsize _lUdialog=dialog # whiptail # gdialog
    local -A _lUdevices
    unset ${1:-REPLY}
    for _lUdisk in /sys/block/*; do
        [ -f $_lUdisk/removable ] && [ $(<$_lUdisk/removable) -gt 0 ] &&
        [ -f $_lUdisk/size ] && [ $(<$_lUdisk/size) -gt 0 ] &&
        txtsize $(<$_lUdisk/size)*512 _lUsize &&
        [ -f $_lUdisk/trace/enable ] && [ -z "$(<$_lUdisk/trace/enable)" ] &&
        _lUdevices[${_lUdisk##*/}]="$_lUsize $(<$_lUdisk/device/model)"
    done
    case ${#_lUdevices[@]} in
        0 ) ;; # echo Sorry no key found. ;;
        1 ) IFS read -a ${1:-REPLY} \
            <<< "${!_lUdevices[@]}§${_lUdevices[@]%% *}§${_lUdevices[@]#* }";;
        * ) declare -a menu
           for _lUdisk in ${!_lUdevices[@]}; do
               menu+=($_lUdisk "${_lUdevices[$_lUdisk]}")
           done
           _lUdisk=$($_lUdialog --menu "Choose a USB stick" \
               $((LINES-3)) $((COLUMNS-3)) $((LINES-8)) \
               "${menu[@]}" 2>&1 >/dev/tty)
           IFS read -a ${1:-REPLY} \
           <<< "$_lUdisk§${_lUdevices[$_lUdisk]%% *}§${_lUdevices[$_lUdisk]#* }"
    esac
}

这将答案(作为数组)分配给作为第一个参数给出的变量或变量$REPLY

chooseFreeUsbKey stick

echo "$stick"
sdf

echo "${stick[1]}"
7.26G

echo "${stick[2]}"
Storage Media

(最后一个字段可能包含空格。)


感谢@StephaneChazelas使我的答案的第一部分更具可读性。
F. Hauri 2013年

1
(1)为什么要嵌套花括号?你是说…,device/{model,type,vendor,uevent}吗 (2)您能解释一下您的GENHD命令和“ trace / enable”命令吗?(3)您的[ $(( $(< $file ) & 1 )) -ne 0 ]测试可以简化为(缩短)(( $(< $file ) & 1 ))
G-Man说“恢复莫妮卡”

@ G-Man(1)是,为此+1!我不了解此技巧是如何引入的。(2)通用硬盘头文件必须位于中/usr/src/*/include/linux。尝试sed -ne 's/#define.*GENHD_FL_\([A-Z0-9_]*\)[ \t]*\([0-9]*\) \?.*$/GENHD_FLAGS[\2]="\1"/p;' /usr/src/*/include/linux/genhd.h。(3)是的。
F. Hauri

0

我建议仅使用hdparmlshw(您可能需要安装),然后使用sudo以root身份执行它。

sudo hdparm -I /dev/sda
sudo lshw -short -C disk
sudo lshw -class disk -class storage

应该都给你信息。


虚拟磁盘上的hdparm:hdparm -i /dev/sda /dev/sda: HDIO_DRIVE_CMD(identify) failed: Invalid exchange HDIO_GET_IDENTITY failed: Invalid argument
蒂姆(Tim)

好吧,我说应该,并且它在这里与虚拟磁盘一起使用。
AugustBitTony 2012年

0

只需读取的值/sys/block/sdX/removable

例如:

$ cat /sys/block/sda/removable
0
$ cat /sys/block/sdc/removable
1

/dev/sdc 是USB密钥(可以是SD卡或任何其他可移动媒体)。


这会在F. Hauri的答案中复制信息,并且不会添加任何新内容。除非您可以添加任何现有答案中未发现的新方面,否则请不要发布答案。
G-Man说'Resstate Monica''May

0

dmesg 是最简单的方法:

dmesg | grep sd X

(是您设备的名称,例如)sdXsda

在上面的命令中,您将看到以下内容:

  • 附加的SCSI磁盘(硬盘)
  • 连接的SCSI可移动磁盘(可移动介质;例如USB闪存驱动器)

dmesg读取内核的循环消息缓冲区,因此此解决方案仅在重新启动后才相对较
新地

0

您可以使用以下命令获取SD,USB和SATA设备节点。

usb_device="/dev/`ls -lR /dev/disk/by-id/  | grep ^l | grep 'usb' | awk '{print $NF}' | cut -d '/' -f 3 | awk 'NR == 1'`"

sata_device="/dev/`ls -lR /dev/disk/by-id/ | grep ^l | grep 'ata' | awk '{print $NF}' | cut -d '/' -f 3 | awk 'NR == 1'`"

sd_device="/dev/`ls -lR /dev/disk/by-id/   | grep ^l | grep 'mmc' | awk '{print $NF}' | cut -d '/' -f 3 | awk 'NR == 1'`"

1
(1)对我来说,这是如何回答问题的,这不是很明显,即“对于任何特定情况/dev/sdX,我怎么知道它是本地HDD还是USB密钥?”请解释一下OP如何使用您的命令来实现这一点判定。(2)仅提供命令的答案相比,我们更喜欢给出命令的答案并对其进行解释。请说明您在做什么。请不要在评论中回复;编辑您的答案,使其更清晰,更完整。…(续)
G-Man说'Resstate Monica''17

(续)…(3)  awk是一个非常强大的工具。许多初学者发布了答案,grep并将答案输出到awk。这很少需要;awk可以进行模式匹配,并且可以在不需要帮助的情况下选择所需的输入grep。您有一条包含两个grep命令的管道,这些管道通过管道传输到中awk,然后是第二个 awk命令。这可以大大简化;请试试。(4)另外,为清楚起见,您可能需要更改`…`$(…)—参见thisthisthis
G-Man说'Resstate Monica''5

0

我很懒,inxi很容易告诉我:

inxi -D
Drives:    HDD Total Size: 1220.3GB (33.2% used)
           ID-1: /dev/sda model: ST380817AS size: 80.0GB
           ID-2: /dev/sdb model: WDC_WD1003FZEX size: 1000.2GB
           ID-3: USB /dev/sdc model: USB_Flash_Drive size: 140.0GB

我相信它还会告诉我是否是火线,也许是其他类型,但是我必须仔细检查,已经有一段时间没有使用这些类型了。

它还告诉我使用-p如果分区是远程的,例如samba或nfs挂载。


-1

插入USB设备后,运行 dmesg在控制台窗口中。您将获得一些提示。

例如,它将说出“插入设备,大容量存储/ dev / sdd”的内容。


2
请提供更多信息/说明,以使您的答案有用。
乔治M

2
回答问题时不侮辱怎么样?
Shadur 2012年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.