5

If lsblk -o NAME,SERIAL,MOUNTPOINT includes the following in its output

sdb                                           X55MM4827123
└─sdb1
  └─luks-4d0dc651-9aa6-452d-9442-7b33d95f8427                /run/media/main/mydrive

What is a simple console/CLI command I can use to get the serial number (X55MM4827123 in this case) when I provide the mountpoint (/run/media/main/mydrive in this case)?

The answer doesn't necessarily have to use lsblk, but it should hopefully be concise and ideally use just simple bash scripting.

3

These options will print your disk serial without headings: lsblk -n -o SERIAL /dev/sda

Options explained, and that can be found at the manpages:

-n, --noheadings
Do not print a header line.

This option will remove headers like Serial: from the command output.

-o, --output list
Specify which output columns to print. Use --help to get a list of all supported columns.

Select what information to print about disks.

This will be enough to bring you only the serial. Unfortunately, lsblk does not work with mountpoints, since the serial is an attribute of the disk, not the partition. Taking a look at the synopsis:

Synopsis

lsblk [options]
lsblk [options] device...

You will have to make a huge effort to extract from the mountpoint the partition, trim the disk information and then, supply it as parameter to lsblk. This will probably do the trick:

mount| grep /run/media/main/mydrive | awk 'NR==1{print $1}'|sed 's/[0-9]*//g'

mount will list all mountpoints, grep will get the line of your mountpoint, awk will get the partition column and sed will remove numbers, that are the representation of partitions. Summing all:

lsblk -n -o SERIAL `mount| grep /run/media/main/mydrive | awk 'NR==1{print $1}'|sed 's/[0-9]*//g'`
3
  • The sed is replacing the numbers, so the mount/grep/awk command results in /dev/mapper/luks-ddc-aa-d--bdf, even though luks should have a uuid after it.
    – user779159
    Jan 13 '17 at 13:33
  • 1
    Oh boy, Forgot that you have a disk encryption based on luks. I've tested with LVM and plain devices but not with those. Give me some time and i will fix this. But now, we have another problem that is: Nested devices. You have a Luks device, created on top of a disk device. This will be hard to fix, since we will have to probe all the possibilities(mdraid, sda, lvm, luks...)
    – user34720
    Jan 13 '17 at 15:35
  • Not sure if it helps but I'm not using lvm or mdraid, just luks.
    – user779159
    Jan 13 '17 at 22:04
0

As far as I understand, the goal is to give the command input as mountpoint and output serial number. Well, it's possible with a small script that uses a little bit of awk magic and smartmontools package.

Demo2:

$ ./mount2serial.sh /                                                                                                    
[sudo] password for xieerqi: 
Serial Number:    4G7AA3Q1HSZ4HH4YN
$ ./mount2serial.sh /mnt/HDD                                                                                             
[sudo] password for xieerqi: 
Serial Number:    4O75CEXFLML9M

And here's script itself:

#!/usr/bin/env bash

if [ "$1" = "/"  ]
then
    dev=$(awk -v mount="$1" '$2 == mount{print $1}' /proc/self/mounts)
else
    dev=$(awk -v mount="$1" '$0 ~ mount{print $1}' /proc/self/mounts)
fi
sudo smartctl -i "$dev" | grep 'Serial Number:'

Since you do get serial number in lsblk, and GNU version1 of lsblk can output JSON data, I've put together a Python script that works as so2:

$ ./mount2serial.py '/mnt/ubuntu'
4O75CEXFLML9M
xie@xie-PC:~$ ./mount2serial.py '/'
B4VOM8OEIZIHF
#!/usr/bin/env python3

import json
import subprocess
import sys

lsblk = subprocess.run(['lsblk','-J','-o','NAME,SERIAL,MOUNTPOINT'],stdout=subprocess.PIPE)
for dev in json.loads(lsblk.stdout.decode())['blockdevices']:
    serial = ''
    # find serial number of current block device
    for key,value in dev.items():
        if key == 'serial':
            serial = value
            break
    # we don't need to iterate through everything in dev.items()
    for child in dev['children']:
        if child['mountpoint'] == sys.argv[1]:
            print(serial)
            sys.exit(0)
# if nothing is found we end up here with exit status 1 and nothing printed
sys.exit(1)

1. I've no idea if non-GNU versions of lsblk exist, but if they do - leave a comment

2. Serial numbers shown are random strings generated from /dev/urandom for demo purposes

3
  • Do you know how to make this work with a luks device? smartctl gives an error "Unable to detect device type".
    – user779159
    Aug 3 '19 at 6:15
  • @user779159 Unfortunately, no, but if I happen to figure it out someday I'll update my answer Aug 3 '19 at 7:53
  • @user779159 Actually, since you do get serial number from lsblk, I've added a Python script that parses output of that command. That's the best solution I can provide thus far Aug 3 '19 at 8:22

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.