How to get drive SERIAL number from mountpoint

command linehard-diskmountscripting

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.

Best Answer

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

Related Question