0

I'm trying to automatically identify which disk (not partition) the OS resides on for a certain program which will format many attached disks (so it doesn't accidently format the OS disk).

I'm currently using dmidecode -s system-uuid, but I think that this gives the parition UUID.

I could ask the user for it, but that would be a hassle.

Is there any way to identify the disk (as in /dev/sdX) and UUID that would be usable in a script format?

If it produces the exact result as in: run CODE_HERE, and gets result /dev/sdX, so much the better :)

System:
  Host: MidnightStarSign Kernel: 5.12.9-1-MANJARO x86_64 bits: 64 compiler: gcc 
  v: 11.1.0 Desktop: KDE Plasma 5.21.5 Distro: Manjaro Linux base: Arch Linux 
Machine:
  Type: Desktop Mobo: ASUSTeK model: PRIME X570-PRO v: Rev X.0x 
  serial: <superuser required> UEFI: American Megatrends v: 3001 
  date: 12/04/2020 
CPU:
  Info: 16-Core model: AMD Ryzen 9 5950X bits: 64 type: MT MCP arch: Zen 3 
  rev: 0 cache: L2: 8 MiB 
  flags: avx avx2 lm nx pae sse sse2 sse3 sse4_1 sse4_2 sse4a ssse3 svm 
  bogomips: 217667 
  Speed: 3728 MHz min/max: 2200/3400 MHz boost: enabled Core speeds (MHz): 
  1: 3728 2: 3664 3: 4122 4: 3754 5: 3678 6: 3659 7: 3682 8: 3661 9: 3670 
  10: 3683 11: 3664 12: 3658 13: 3660 14: 4580 15: 3660 16: 4585 17: 3668 
  18: 4585 19: 3662 20: 3671 21: 3662 22: 3670 23: 3660 24: 3662 25: 3661 
  26: 3661 27: 3732 28: 3662 29: 4573 30: 3721 31: 4575 32: 3681 
Graphics:
  Device-1: NVIDIA GA104 [GeForce RTX 3070] vendor: ASUSTeK driver: nvidia 
  v: 465.31 bus-ID: 0b:00.0 
  Device-2: Microdia USB 2.0 Camera type: USB driver: snd-usb-audio,uvcvideo 
  bus-ID: 7-1:2 
  Display: x11 server: X.Org 1.20.11 driver: loaded: nvidia resolution: 
  1: 1920x1080~60Hz 2: 1920x1080 3: 1920x1080 
  OpenGL: renderer: NVIDIA GeForce RTX 3070/PCIe/SSE2 v: 4.6.0 NVIDIA 465.31 
  direct render: Yes 
Audio:
  Device-1: NVIDIA vendor: ASUSTeK driver: snd_hda_intel v: kernel 
  bus-ID: 0b:00.1 
  Device-2: AMD Starship/Matisse HD Audio vendor: ASUSTeK driver: snd_hda_intel 
  v: kernel bus-ID: 0e:00.4 
  Device-3: JMTek LLC. Plugable USB Audio Device type: USB 
  driver: hid-generic,snd-usb-audio,usbhid bus-ID: 3-1:2 
  Device-4: Schiit Audio Schiit Modi 3+ type: USB driver: snd-usb-audio 
  bus-ID: 3-2:3 
  Device-5: ASUSTek ASUS AI Noise-Cancelling Mic Adapter type: USB 
  driver: hid-generic,snd-usb-audio,usbhid bus-ID: 5-5:3 
  Device-6: Microdia USB 2.0 Camera type: USB driver: snd-usb-audio,uvcvideo 
  bus-ID: 7-1:2 
  Sound Server-1: ALSA v: k5.12.9-1-MANJARO running: yes 
  Sound Server-2: JACK v: 0.125.0 running: no 
  Sound Server-3: PulseAudio v: 14.2 running: yes 
  Sound Server-4: PipeWire v: 0.3.30 running: yes 
Network:
  Device-1: Realtek RTL8125 2.5GbE driver: r8169 v: kernel port: d000 
  bus-ID: 05:00.0 
  IF: enp5s0 state: up speed: 1000 Mbps duplex: full mac: 3c:7c:3f:a6:c3:22 
  Device-2: Intel I211 Gigabit Network vendor: ASUSTeK driver: igb v: kernel 
  port: c000 bus-ID: 07:00.0 
  IF: enp7s0 state: down mac: 24:4b:fe:5b:08:2a 
Bluetooth:
  Device-1: Cambridge Silicon Radio Bluetooth Dongle (HCI mode) type: USB 
  driver: btusb v: 0.8 bus-ID: 3-5.3:6 
  Report: rfkill ID: hci0 rfk-id: 0 state: up address: see --recommends 
Drives:
  Local Storage: total: 3.89 TiB used: 1.83 TiB (47.1%) 
  ID-1: /dev/nvme0n1 vendor: Western Digital model: WDS100T3X0C-00SJG0 
  size: 931.51 GiB 
  ID-2: /dev/nvme1n1 vendor: Western Digital model: WDS100T2B0C-00PXH0 
  size: 931.51 GiB 
  ID-3: /dev/sda vendor: Seagate model: ST2000LM015-2E8174 size: 1.82 TiB 
  ID-4: /dev/sdb type: USB vendor: Generic model: USB3.0 CRW -SD 
  size: 119.08 GiB 
  ID-5: /dev/sdd type: USB vendor: Samsung model: Flash Drive FIT 
  size: 119.51 GiB 
  ID-6: /dev/sde type: USB vendor: Toshiba model: TransMemory size: 14.92 GiB 
  ID-7: /dev/sdf type: USB vendor: SanDisk model: Gaming Xbox 360 size: 7.48 GiB 
Partition:
  ID-1: / size: 767 GiB used: 726.35 GiB (94.7%) fs: btrfs dev: /dev/dm-0 
  mapped: luks-466d5812-64c7-4a28-bcc4-a1a5adfa9450 
  ID-2: /boot/efi size: 511 MiB used: 26.1 MiB (5.1%) fs: vfat 
  dev: /dev/nvme0n1p1 
  ID-3: /home size: 767 GiB used: 726.35 GiB (94.7%) fs: btrfs dev: /dev/dm-0 
  mapped: luks-466d5812-64c7-4a28-bcc4-a1a5adfa9450 
Swap:
  ID-1: swap-1 type: partition size: 64 GiB used: 128.2 MiB (0.2%) 
  dev: /dev/dm-1 mapped: luks-81b2dc57-06f5-4471-b484-77c3a516f307 
Sensors:
  System Temperatures: cpu: 79.6 C mobo: 0 C gpu: nvidia temp: 41 C 
  Fan Speeds (RPM): N/A gpu: nvidia fan: 0% 
Info:
  Processes: 964 Uptime: 1d 4h 28m Memory: 62.78 GiB used: 39.02 GiB (62.2%) 
  Init: systemd Compilers: gcc: 11.1.0 clang: 12.0.0 Packages: 2014 Shell: Bash 
  v: 5.1.8 inxi: 3.3.04 
1
  • LVM could be a problem, since it would cover multiple disks. Jul 7, 2021 at 2:11

2 Answers 2

1

I don't think it's possible to easily solve the general case. But it's not too hard for very basic cases. Getting the root partition is as simple as running df -h /. Now a partition is either /dev/sdXdigit (eventually /dev/hdXdigit) or /dev/xxxxxpdigit where xxxxx is something like nvme0n1 or mmcblk0. So in the simple case, getting the system disk is relatively straight forward :

  1. get the / partition name
    • if part name ends in digitpdigits, remove pdigits
    • otherwise just remove the trailing digits

You could do it like this :

df -h / | awk '
  NR == 2 && $1 ~ /[0-9]p[0-9]+$/ {
    disk=$1
    sub( /p[0-9]+$/, "", disk )
    print disk
  }
  NR == 2 && $1 ~ /[sh]d.[0-9]+$/ {
    disk=$1
    sub( /[0-9]+$/, "", disk )
    print disk
  }
'

But the general case is really complicated. / could be on an lvm volume, built on top of a crypto device itself built on top some raid device involving at least 2 disks (or lvm < raid < crypto) or it could be on a multipathed device ( 2 controllers get to the same device for redundancy and you end up with 2 device names for one physical device) or on a zfs raid or I don't know...

So maybe you are interrested in the boot disk, the one where /boot/efi is, assuming that your system boots in EFI mode. In this case, just replace df -h / by df -h /boot/efi and you're good. Why use /boot/efi ? Because EFI firmware can only boot simple partitions, not zfs raid, luks, linux raid or other weird things that Linux can use. Note that you still have the problem of detecting system disks ; it's perfectly possible to have /boot/efi somewhere on /dev/sda and / on /dev/sdb or on zfs raid, lvm, linux raid etc...

0

You could try stat / - or a formatted version thereof.

The output will look like

File: /
  Size: 4096        Blocks: 8          IO Block: 4096   directory
Device: 10302h/66306d   Inode: 2           Links: 19
Access: (0755/drwxr-xr-x)  Uid: (    0/    root)   Gid: (    0/    root)
[...]

The device information :- 10302 in hex can be decoded as 103h = 259 decimal (an nvme device) and 02h = partition 2.

lsblk confirms this (in decimal)

nvme0n1     259:0    0 238.5G  0 disk 
├─nvme0n1p1 259:1    0   260M  0 part /boot/efi
├─nvme0n1p2 259:2    0  48.8G  0 part /
└─nvme0n1p3 259:3    0  48.8G  0 part /mnt/linux

It should be possible to obtain more script-friendly output from these two commands.

blkid can be used to get the partition UUID.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.