9

I am writing an installation automation BASH script. I'd like to install the nvme-cli package only if an NVMe SSD is actually present. I couldn't find a simple way to query the hardware (say, using lshw) to get a kind-of-yes-or-no answer. Any of you can give a way to extract the specific answer from within a BASH script? I'd like to use the case conditioning to either install it or not.

muru
  • 193,181
  • 53
  • 473
  • 722
PenguinCSC
  • 1,426
  • 2
  • 14
  • 26
  • 1
    Is there some reason to not install the package regardless? Its not big. And there may be a case where hardware gets upgraded later, after the installation. – Criggie May 31 '21 at 03:25
  • Are these physical hosts of various specs, or are you using virtual machines ? – Criggie May 31 '21 at 03:37

6 Answers6

14

A directory test is sufficient:
(the path /sys/class/nvme is created by the module nvme. However, this does not say anything about the operational state of the drive(s) or even if a drive exists, though).

#!/bin/bash

if [[ -d /sys/class/nvme ]]; then
  apt-get -y install nvme-cli
fi

Or, if you prefer using globbing to check for the existence of a file(s), a for-loop will have the advantage of avoiding a subshell:

shopt -s nullglob
for _ in /dev/nvme*; do
  apt-get -y install nvme-cli; break
done

Also, if you can, you should avoid globbing as an argument, where there are alternatives, e.g., in this case, the use of echo or printf is preferable (which is, in reality, a loop construct).

shopt -s nullglob
if [[ -n $(echo /dev/nvme*) ]]; then
  apt-get -y install nvme-cli
fi
4

Check to see if any nvme device files exist:

if ls /dev/nvme*
then 
    echo "Install NVME-CLI" 
fi
user10489
  • 3,564
  • 2
  • 5
  • 22
4
dmesg | grep -q nvme
if [ $? = 0 ]  ; then 
      apt install nvme-cli -y
fi

All of these solutions should work about the same; they're all testing to see if the kernel has found a NVME device in any way.

If the installer runs at boot, this is probably adequate. If the installer might run long after boot, then the first line would be better as:

grep -q nvme /var/log/dmesg
Criggie
  • 671
  • 5
  • 12
  • Thank you all. I havn't realised it is so simple a solution... – PenguinCSC May 31 '21 at 11:31
  • 7
    Kernel message buffer is a ring buffer. If a lot of messages have been emitted (e.g. due to long uptime), they'll overwrite the older ones, and this method will give false negative. – Ruslan May 31 '21 at 13:17
  • @Ruslan excellent point. – Criggie May 31 '21 at 19:39
  • 1
    It's worth noting that, while this might work on Ubuntu, other linux setups might have access to dmesg restricted to the root user. So, if you're planning to run this on other distros, or if ubuntu changes kernel.dmesg_restrict, you might want to use a different approach. – Nonny Moose May 31 '21 at 20:53
3

Try using lsscsi:

 NVMECOUNT=`lsscsi | grep nvme | wc -l`
    if [ $NVMECOUNT -gt 1 ]
    then 
        echo "Install NVME-CLI" 
    fi
  • 1
    `lsscsi` isn't installed as default, it may seem a bit unnecessary to install one package to test if you need to install another. –  May 31 '21 at 00:58
2

Check if the nvme driver is loaded

if grep -q nvme /proc/devices
then 
    echo "Install NVME-CLI" 
fi
user10489
  • 3,564
  • 2
  • 5
  • 22
2

In some cases, free space is an issue, besides, i am a firm believer in not installing redundant packaged as a rule, so, eventually I went with:

 NVMECOUNT=`lsblk | grep nvme | wc -l`
    if [ $NVMECOUNT -gt 1 ]
    then 
        apt -y install nvme-cli
    fi

Thanks!

PenguinCSC
  • 1,426
  • 2
  • 14
  • 26