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$, если какое-либо из полей изменяет значение.
Существует несколько способов сказать без полномочий пользователя 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
перечисленный оба)
Существуют другие также, более или менее прямые, чем эти.
Я знаю решение, но, к сожалению, оно требует полномочия пользователя 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
[...]
Я предлагаю просто использовать hdparm
или lshw
(который Вы, возможно, должны были бы установить), и использование sudo
выполнить его как корень.
sudo hdparm -I /dev/sda
sudo lshw -short -C disk
sudo lshw -class disk -class storage
должен все дать Вам информацию.
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
После того, как Вы включаете USB-устройство, работаете dmesg
в консоли. Вам предоставят некоторые подсказки.
Например, это будет говорить что-то вроде "Включенного устройства, массовое хранение/dev/sdd".
Этому не нужны полномочия пользователя 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
(Последнее поле может содержать пробелы.)
…,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
/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-карта или любой другой съемный носитель).
dmesg
- самый простой способ:
dmesg | grep sdX
( sd X
- имя вашего устройства, например, sda
)
Из команды выше вы увидите следующее:
Вы можете использовать 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
Я ленивый, 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.
С помощью приведенных ниже команд можно получить узлы устройств 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'`"
В 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
^^^^
esatap
? – CMCDragonkai 01.11.2015, 11:07