Hello. This is my first post to this forum. I've read many of the posts over the last two or three years and I've learned a lot.
I'm creating a live Linux distribution using the Linux Live Scripts -- just as a hobby project -- and I'm wanting to create an automated way for a user to copy the folders on the boot CD to a connected flash drive. The interface for that function should be a menu listing of the drive or drives. It should display:
- the manufacturer (i.e., Kingston)
- the model (i.e., Data Traveler)
- the capacity in the format "512MB" or "1GB" or "4GB"
- the path (i.e. /mnt/sda1)
The user would select the drive and the copy would begin.
I've got a ton of books and I'm pounding topics like awk and grep into my head, but I'm almost 50 and not as bright as I used to be :). I could probably do it, but I'm about about three months out if I insist on figuring it out on my own. And although that might build character, if someone has already created such a script I'd really rather just grab that code and modify it.
LSHW seems like an obvious way to get the device information, but I'm good with any method. Has anyone out there done such a BASH script already? My Google searches have failed to find one. Thanks in advance for any thoughts or suggestions.
Godz
It's not quite a simple script because it involves tying several sources of information together. The point of the UNIX device model is to make it irrelevant whether a device is USB or IDE or SCSI or whatever from a programmer's point of view, getting all the info you need would mean tying together info from /sys/, lsusb, and possibly udev as well... Does linux live have udev?
Here is the start of something combining info from /sys/ with udev. From here we see that not all manufacturers encode their USB devices with any sort of sane, or even identifiable code values... This readout is from a generic MP3 player device with an occupied card-slot, the 512M of built-in storage is sdb and the card slot is sdc.
#!/bin/bash
for DEV in /sys/block/sd*
do
if readlink $DEV/device | grep -q usb
then
DEV=`basename $DEV`
echo "$DEV is a USB device, info:"
udevinfo --query=all --name $DEV
if [ -d /sys/block/${DEV}/${DEV}1 ]
then
echo "Has partitions " /sys/block/$DEV/$DEV[0-9]*
else
echo "Has no partitions"
fi
echo
fi
done
exit 0
$ ./getusb.sh
sdb is a USB device, info:
P: /block/sdb
N: sdb
S: disk/by-id/usb-SMI_USB_DISK_AA04012700498000-0:0
S: disk/by-path/pci-0000:00:0b.1-usb-0:1:1.0-scsi-0:0:0:0
S: disk/by-uuid/F4E6-8AEC
E: DEVTYPE=disk
E: ID_VENDOR=SMI
E: ID_MODEL=USB_DISK
E: ID_REVISION=4000
E: ID_SERIAL=SMI_USB_DISK_AA04012700498000-0:0
E: ID_SERIAL_SHORT=AA04012700498000
E: ID_TYPE=disk
E: ID_INSTANCE=0:0
E: ID_BUS=usb
E: ID_PATH=pci-0000:00:0b.1-usb-0:1:1.0-scsi-0:0:0:0
E: ID_FS_USAGE=filesystem
E: ID_FS_TYPE=vfat
E: ID_FS_VERSION=FAT16
E: ID_FS_UUID=F4E6-8AEC
E: ID_FS_UUID_ENC=F4E6-8AEC
E: ID_FS_LABEL=
E: ID_FS_LABEL_ENC=
E: ID_FS_LABEL_SAFE=
Has no partitions
sdc is a USB device, info:
P: /block/sdc
N: sdc
S: disk/by-id/usb-SMI_USB_DISK_AA04012700498000-0:1
S: disk/by-path/pci-0000:00:0b.1-usb-0:1:1.0-scsi-0:0:0:1
E: DEVTYPE=disk
E: ID_VENDOR=SMI
E: ID_MODEL=USB_DISK
E: ID_REVISION=4000
E: ID_SERIAL=SMI_USB_DISK_AA04012700498000-0:1
E: ID_SERIAL_SHORT=AA04012700498000
E: ID_TYPE=disk
E: ID_INSTANCE=0:1
E: ID_BUS=usb
E: ID_PATH=pci-0000:00:0b.1-usb-0:1:1.0-scsi-0:0:0:1
Has partitions /sys/block/sdc/sdc1
$
Thanks, Corona, for those replies; however, I believe that the LSHW utility will do nicely for gathering the information I'm wanting to list for the users. Here is a sample output from my machine. Two flash drives are connected (one of them older and painfully small -- 64MB -- the other 1GB).
This is the result of the "lshw -short" command.
H/W path Device Class Description
==========================================================
system PROD00000000
/0 bus Motherboard
/0/0 processor Intel(R) Pentium(R) 4 CPU 2.00GHz
/0/0/0 memory 8KiB L1 cache
/0/0/1 memory 512KiB L2 cache
/0/1 memory 2021MiB System memory
/0/100 bridge 651 Host
/0/100/1 bridge Virtual PCI-to-PCI bridge (AGP)
/0/100/1/0 display NV44A [GeForce 6200]
/0/100/2 bridge SiS962 [MuTIOL Media IO]
/0/100/2.1 bus SiS961/2 SMBus Controller
/0/100/2.5 storage 5513 [IDE]
/0/100/2.5/0 ide0 bus IDE Channel 0
/0/100/2.5/0/0 /dev/hda disk 160GB SAMSUNG SP1604N
/0/100/2.5/0/0/1 /dev/hda1 volume 127GiB Windows NTFS volume
/0/100/2.5/0/0/2 /dev/hda2 volume 21GiB Windows NTFS volume
/0/100/2.5/0/1 /dev/hdb disk 81GB Maxtor 6L080L0
/0/100/2.5/0/1/1 /dev/hdb1 volume 76GiB EXT3 volume
/0/100/2.5/1 ide1 bus IDE Channel 1
/0/100/2.5/1/0 /dev/hdc disk SONY DVD RW DW-Q30A
/0/100/2.5/1/0/0 /dev/hdc disk
/0/100/2.5/1/1 /dev/hdd disk LITE-ON LTR-52327S
/0/100/2.7 multimedia AC'97 Sound Controller
/0/100/3 bus USB 1.1 Controller
/0/100/3/1 usb4 bus OHCI Host Controller
/0/100/3.1 bus USB 1.1 Controller
/0/100/3.1/1 usb5 bus OHCI Host Controller
/0/100/3.3 bus USB 2.0 Controller
/0/100/3.3/1 usb1 bus EHCI Host Controller
/0/100/a bus USB
/0/100/a/1 usb6 bus OHCI Host Controller
/0/100/a.1 bus USB
/0/100/a.1/1 usb7 bus OHCI Host Controller
/0/100/a.1/1/1 input Microsoft IntelliMouse
/0/100/a.2 bus USB 2.0
/0/100/a.2/1 usb2 bus EHCI Host Controller
/0/100/a.2/1/3 scsi2 storage Flash Disk
/0/100/a.2/1/3/0.0.0 /dev/sda disk 1029MB SCSI Disk
/0/100/a.2/1/3/0.0.0/1 /dev/sda1 volume 981MiB Windows FAT volume
/0/100/b bus VT82xxxxx UHCI USB 1.1 Controller
/0/100/b/1 usb8 bus UHCI Host Controller
/0/100/b/1/1 scsi3 storage Mass Storage Device
/0/100/b/1/1/0.0.0 /dev/sdb disk 65MB SCSI Disk
/0/100/b/1/1/0.0.0/1 /dev/sdb1 volume 62MiB Windows FAT volume
/0/100/b.1 bus VT82xxxxx UHCI USB 1.1 Controller
/0/100/b.1/1 usb9 bus UHCI Host Controller
/0/100/b.2 bus USB 2.0
/0/100/b.2/1 usb3 bus EHCI Host Controller
/0/100/d eth0 network RTL-8139/8139C/8139C+
Only takes a couple of seconds. True, lshw tends to view flash drives as SCSI devices, but I don't see that as a dealbreaker.
Another way to do what you want is to query the devices using the hal-* utilities which are available on most modern GNU/Linux distributions.
#!/bin/ksh93
for udi in $(/usr/bin/hal-find-by-capability --capability storage)
do
device=$(hal-get-property --udi $udi --key block.device)
vendor=$(hal-get-property --udi $udi --key storage.vendor)
model=$(hal-get-property --udi $udi --key storage.model)
if [[ $(hal-get-property --udi $udi --key storage.bus) = "usb" ]]
then
parent_udi=$(hal-find-by-property --key block.storage_device --string $udi)
mount=$(hal-get-property --udi $parent_udi --key volume.mount_point)
label=$(hal-get-property --udi $parent_udi --key volume.label)
media_size=$(hal-get-property --udi $udi --key storage.removable.media_size)
size=$(( ceil(media_size/(1000*1000*1000)) ))
printf "$vendor $model $device $mount $label "${size}GB" \n"
fi
done
Here is the output for two USB thumb drives
$ ./listusb
Kingston DataTraveler 2.0 /dev/sdd /media/KINGSTON KINGSTON 1GB
Kingston DataTraveler 2.0 /dev/sdc /media/USB-4GB USB-4GB 4GB
Thanks, pfmurphy. That's a huge help.
A system with SATA will consider those drives as SCSI as well.. in fact, on newer linux systems, it will consider IDE drives as SCSI too.
Corona: that's true, I did notice that when I was testing lshw. So fpmurphy's script does much better.