How to find the disk where root / is on in Bash on Linux?
Posted on In Linux, QA, TutorialQuestion: how to find the disk where the Linux’s root(/) is on in Bash? The root may be on a LVM volume or on a raw disk.
2 cases:
One example:
# df -hT | grep /$
/dev/sda4 ext4 48G 32G 14G 71% /
For another example:
# df -hT | grep /$
/dev/mapper/fedora-root ext4 48G 45G 1.4G 98% /
The it is a LVM volume in LVM group ‘fedora’:
# lvs | grep fedora | grep root
root fedora -wi-ao---- 48.83g
and ‘fedora’ is on the single disk partition ‘/dev/sda3’ of disk ‘/dev/sda’:
# pvs | grep fedora
/dev/sda3 fedora lvm2 a-- 64.46g 4.00m
For both cases above, we want to find out ‘/dev/sda’ (the root filesystem is on only one physical disk).
To solve this problem, one straightforward way is to check every possible cases and handle each case following the format for each case (raw partition, or LVM partition). But in Linux, there is a more convenient tool to handle this problem – using lsblk
.
Table of Contents
lsblk
and PKNAME
lsblk
can show one important value here:
PKNAME internal parent kernel device name
For a raw partition, the parent kernel device is the disk, and for an LVM partition, the parent kernel device is the physical volume (the partition). Here are examples of output of lsblk
.
For a ‘/’ on a raw partition:
root@vm0:~# lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
...
sdc 8:32 0 1.8T 0 disk
├─sdc1 8:33 0 512M 0 part /boot/efi
└─sdc2 8:34 0 1.8T 0 part /
For a ‘/’ on an LVM partition:
root@vm1:~# lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sda 8:0 0 20G 0 disk
├─sda1 8:1 0 512M 0 part /boot/efi
├─sda2 8:2 0 1K 0 part
└─sda5 8:5 0 19.5G 0 part
├─vgubuntu-root 253:0 0 18.5G 0 lvm /
└─vgubuntu-swap_1 253:1 0 976M 0 lvm [SWAP]
PKNAME
for raw or LVM partition backed root ‘/’
From lsblk
‘s manual, we can see it supports various output format. Here, we use the key/value pair format which is easy to parse in Bash.
For raw partition based ‘/’:
# lsblk -oMOUNTPOINT,PKNAME -P | grep 'MOUNTPOINT="/"'
MOUNTPOINT="/" PKNAME="sdc"
For LVM partition based ‘/’:
# lsblk -oMOUNTPOINT,PKNAME -P | grep 'MOUNTPOINT="/"'
MOUNTPOINT="/" PKNAME="sda5"
We can easily get rid of the trailing numbers (so we get the disk device name) by
sed 's/[0-9]*$//'
This can be applied to both cases. For the raw partition case, the sed
command simply does not have any additional effect.
Wrap up to be a bash statement
Now, we can wrap all up into a bash statement using some Bash grammar and techniques
dev=$(eval $(lsblk -oMOUNTPOINT,PKNAME -P -M | grep 'MOUNTPOINT="/"'); echo $PKNAME | sed 's/[0-9]*$//')
For the raw partition case, we get
root@vm0:~# dev=$(eval $(lsblk -oMOUNTPOINT,PKNAME -P -M | grep 'MOUNTPOINT="/"'); echo $PKNAME | sed 's/[0-9]*$//')
root@vm0:~# echo $dev
sdc
For the LVM partition case, we get
root@vm1:~# dev=$(eval $(lsblk -oMOUNTPOINT,PKNAME -P | grep 'MOUNTPOINT="/"'); echo $PKNAME | sed 's/[0-9]*$//')
root@vm1:~# echo $dev
sda