Как знать, является ли/dev/sdX связанный USB или жесткий диск?

awk -v copies=3 -v spacer=_ '
  BEGIN {OFS=FS=","} 
  {
    field1 = $1
    for (i=1; i <= copies+1; i++) {
      $1 = sprintf("%s%s%03d", field1, spacer, i)
      print
    }  
    print ""
  }
'

Это использует в своих интересах awk перевычисление 0$, если какое-либо из полей изменяет значение.

23
10.05.2017, 23:39
11 ответов

Существует несколько способов сказать без полномочий пользователя root, многих из них tricky/hacky:

Используя /dev/disk/by-id:

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

Если это отвечает чем-то как /dev/disk/by-id/usb-blah-blah-blah, затем это - диск USB. Другие префиксы включают ata, dm, memstick, scsi, и т.д.

Используя /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 установленный, ответ Huygens' может также работать:

lshw -class disk -class storage | less

И просмотрите вывод для своего диска. В less, попробуйте / sdX и посмотрите на предыдущее, bus info строки — первая просто скажет scsi@…, но несколько строк, прежде чем это будет более поучительно. Однако действительно необходимо выполнить это как суперпользователь, таким образом, это не может подойти. (признаки: на ноутбуке я попробовал его, это перечислило диск SATA, но не USB один — работающий с sudo перечисленный оба)

Существуют другие также, более или менее прямые, чем эти.

15
27.01.2020, 19:41
  • 1
    Есть ли способы сказать независимо внутренний диск SATA по сравнению с внешним диском SATA, подключенным esatap? –  CMCDragonkai 01.11.2015, 11:07

Я знаю решение, но, к сожалению, оно требует полномочия пользователя 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
[...]
10
27.01.2020, 19:41

Я предлагаю просто использовать hdparm или lshw (который Вы, возможно, должны были бы установить), и использование sudo выполнить его как корень.

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

должен все дать Вам информацию.

0
27.01.2020, 19:41
  • 1
    hdparm на виртуальном диске: hdparm -i /dev/sda /dev/sda: HDIO_DRIVE_CMD(identify) failed: Invalid exchange HDIO_GET_IDENTITY failed: Invalid argument –  Tim 06.06.2012, 16:47
  • 2
    Ну, я сказал, должен и это работать здесь с виртуальными дисками. –  EightBitTony 06.06.2012, 16:52

После того, как Вы включаете USB-устройство, работаете dmesg в консоли. Вам предоставят некоторые подсказки.

Например, это будет говорить что-то вроде "Включенного устройства, массовое хранение/dev/sdd".

-1
27.01.2020, 19:41
  • 1
    Предоставьте больше информации/разъяснения для создания ответа полезным. –  George M 06.06.2012, 16:20
  • 2
    Как насчет того, чтобы не быть оскорбительным при ответе на вопрос? –  Shadur 08.06.2012, 14:30

Этому не нужны полномочия пользователя root (но многие из этих команд используют и зависят от bashisms, таким образом, они не будут работать во всех совместимых POSIX оболочках):

Существует быстрый способ спросить о a 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 у меня есть a 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 значение (который является 52 в моем sda пример, выше), имеет 1 набор битов (т.е. является ли это нечетным числом).

Но Linux представляет все флаги в /sys, так просьба о /sys/block/sdX/removable намного более просто!;-)

Таким образом, флеш-карта могла быть removable, но как существует много съемных устройств, я предпочел бы удостоверяться, что размер носителя больше, чем 0 (как разгруженный лоток CD-ROM для образца) и что устройство не используется: В наблюдении этого sdX/trace/enable не связывается:

Nota: Все это хорошо тестируется на ударе 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 флеш-карты, но один из них (sde) уже смонтирован, таким образом, предыдущий вывод команды:

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

Мой сценарий:

Существует немного функции , которую я записал для установки обновленного Живого Debian.

#!/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

(Последнее поле может содержать пробелы.)

4
27.01.2020, 19:41
  • 1
    Благодаря @StephaneChazelas для того, чтобы сделать первую часть моего ответа более читаемой. –  F. Hauri 05.01.2013, 21:34
  • 2
    (1)  Why у Вас есть вложенные фигурные скобки?   Делают Вы имеете в виду …,device/{model,type,vendor,uevent}?   (2)  Can Вы объясните свои команды GENHD и Ваш “прослеживать/разрешать” команды?   (3)  Your [ $(( $(< $file ) & 1 )) -ne 0 ] тест может быть упрощен (сокращенный) до (( $(< $file ) & 1 )). –  G-Man Says 'Reinstate Monica' 10.05.2017, 23:40
  • 3
    @G-Man (1) Да, +1 для этого! Я не понимаю, как этот tipo был представлен. (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 11.05.2017, 09:21

Просто прочитайте значение / sys / block / sdX / removeable .

Например:

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

/ dev / sdc - это USB-ключ (это может быть SD-карта или любой другой съемный носитель).

0
27.01.2020, 19:41

dmesg - самый простой способ:

dmesg | grep sdX

( sd X - имя вашего устройства, например, sda )

Из команды выше вы увидите следующее:

  • Присоединенный SCSI-диск (жесткий диск)
  • Присоединенный съемный SCSI-диск (съемный носитель; например, USB-накопитель)
0
27.01.2020, 19:41

Вы можете использовать lsblk :

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

где -d или - nodeps означает не печатать ведомые устройства, а -o имя, tran или - имя выхода, tran означает список только имени устройства и типа транспорта устройства. Добавьте rm в список выходных столбцов, чтобы увидеть, какие устройства являются съемными ( 1 , если true ):

lsblk --nodeps --output NAME,TRAN,RM
NAME TRAN   RM
sda  sata    0
sdb  sata    0
sdd  usb     1
8
27.01.2020, 19:41

Я ленивый, 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

Я думаю, что он также говорит мне, если это FireWire и, возможно, какой-то другой тип, но я должен перепроверить, не использовал эти типы какое-то время .

Это также говорит мне использовать -p, если разделы являются удаленными, например, монтирование samba или nfs.

0
27.01.2020, 19:41

С помощью приведенных ниже команд можно получить узлы устройств 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'`"
0
27.01.2020, 19:41

В Linux вы можете получить полный путь к любому устройству из sysfs. Никаких привилегий не нужно.

Для каждого блочного устройства существует символическая ссылка видаmajor:minor(в десятичной форме )внутри /sys/dev/block, указывающая на полный путь устройства по всем шинам. То же самое для символьных устройств внутри /sys/dev/char. Вот пример, который также должен работать на устройствах без bash, stat, util -linux, udev, lshw, hdparm, sudo, perl/python, jq, golang и т. д.:

syspath(){ readlink -f /sys/dev/$(ls -l "$1" | awk -F'[, ]+' '{print ($1~/^c/?"char/":"block/")$5":"$6}'); }

syspath /dev/sda
/sys/devices/platform/scb/fd500000.pcie/pci0000:00/0000:00:00.0/0000:01:00.0/usb2/2-1/2-1:1.0/host0/target0:0:0/0:0:0:0/block/sda
                                                                             ^^^^
0
26.09.2021, 17:22

Теги

Похожие вопросы