193 lines
7.1 KiB
Bash
Executable File
193 lines
7.1 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Gathers disk info including:
|
|
# Hardware info
|
|
# Filesystem data
|
|
# Btrfs array membership
|
|
# LUKS encryption
|
|
# SMART status
|
|
#
|
|
# Usage: sudo ./drive-info.sh
|
|
#
|
|
# Requires root privileges for complete information access
|
|
|
|
# Check for root privileges
|
|
if [[ $EUID -ne 0 ]]; then
|
|
echo "This script must be run as root for complete information"
|
|
exit 1
|
|
fi
|
|
|
|
# Get list of block devices (excluding loop devices, partitions, and virtual devices)
|
|
devices=$(lsblk -dn -o NAME,TYPE | grep disk | awk '{print $1}')
|
|
|
|
for device in $devices; do
|
|
dev_path="/dev/$device"
|
|
|
|
# Get basic size info
|
|
size=$(lsblk -dno SIZE "$dev_path" 2>/dev/null)
|
|
|
|
# Get comprehensive SMART information
|
|
smart_info=$(smartctl -i "$dev_path" 2>/dev/null)
|
|
smart_health=$(smartctl -H "$dev_path" 2>/dev/null | grep "SMART overall-health" | awk '{print $NF}')
|
|
smart_all=$(smartctl -A "$dev_path" 2>/dev/null)
|
|
|
|
# Extract model
|
|
model=$(echo "$smart_info" | grep "Device Model:" | cut -d: -f2- | xargs)
|
|
[[ -z "$model" ]] && model=$(echo "$smart_info" | grep "Model Number:" | cut -d: -f2- | xargs)
|
|
[[ -z "$model" ]] && model=$(cat "/sys/block/$device/device/model" 2>/dev/null | xargs)
|
|
|
|
# Extract serial number
|
|
serial=$(echo "$smart_info" | grep "Serial Number:" | cut -d: -f2- | xargs)
|
|
[[ -z "$serial" ]] && serial=$(lsblk -dno SERIAL "$dev_path" 2>/dev/null)
|
|
|
|
# Extract WWN
|
|
wwn=$(echo "$smart_info" | grep "LU WWN Device Id:" | cut -d: -f2- | xargs | sed 's/ //g')
|
|
[[ -z "$wwn" ]] && wwn=$(lsblk -dno WWN "$dev_path" 2>/dev/null)
|
|
|
|
# Extract rotation rate
|
|
rpm=$(echo "$smart_info" | grep "Rotation Rate:" | cut -d: -f2- | xargs)
|
|
if [[ -z "$rpm" || "$rpm" == "Solid State Device" ]]; then
|
|
rot=$(cat "/sys/block/$device/queue/rotational" 2>/dev/null)
|
|
[[ "$rot" == "0" ]] && rpm="SSD"
|
|
fi
|
|
|
|
# Extract form factor
|
|
form_factor=$(echo "$smart_info" | grep "Form Factor:" | cut -d: -f2- | xargs)
|
|
|
|
# Extract interface and link speed
|
|
interface=$(echo "$smart_info" | grep "SATA Version" | cut -d: -f2- | xargs)
|
|
[[ -z "$interface" ]] && interface=$(echo "$smart_info" | grep "Transport protocol:" | cut -d: -f2- | xargs)
|
|
[[ -z "$interface" ]] && interface=$(echo "$smart_info" | grep "NVMe Version:" | cut -d: -f2- | xargs | awk '{print "NVMe " $1}')
|
|
|
|
# Extract temperature
|
|
temp=$(echo "$smart_all" | grep -i "Temperature" | head -1 | awk '{print $10}')
|
|
[[ -n "$temp" ]] && temp="${temp}°C"
|
|
|
|
# Extract power-on hours
|
|
power_hours=$(echo "$smart_all" | grep "Power_On_Hours" | awk '{print $10}')
|
|
[[ -z "$power_hours" ]] && power_hours=$(echo "$smart_all" | grep "Power On Hours" | awk '{print $3}')
|
|
|
|
# Get disk ID
|
|
disk_id=""
|
|
for f in /dev/disk/by-id/*; do
|
|
[[ -e "$f" ]] || continue
|
|
# resolve symlink target and compare basename to device, skip entries that reference partitions
|
|
target=$(readlink -f "$f" 2>/dev/null) || continue
|
|
if [[ "$(basename "$target")" == "$device" && "$f" != *part* ]]; then
|
|
disk_id=$(basename "$f")
|
|
break
|
|
fi
|
|
done
|
|
|
|
# Get filesystem UUID
|
|
uuid=$(lsblk -no UUID "$dev_path" 2>/dev/null | head -1)
|
|
[[ -z "$uuid" ]] && uuid=$(lsblk -no UUID "${dev_path}1" 2>/dev/null)
|
|
|
|
# Check for LUKS encryption
|
|
luks_uuid=""
|
|
luks_mapper=""
|
|
if cryptsetup isLuks "$dev_path" 2>/dev/null; then
|
|
luks_uuid=$(cryptsetup luksUUID "$dev_path" 2>/dev/null)
|
|
for mapper in /dev/mapper/luks-*; do
|
|
[[ -e "$mapper" ]] || continue
|
|
mapper_name=$(basename "$mapper")
|
|
[[ "$mapper_name" == "luks-$luks_uuid" ]] && luks_mapper="$mapper_name" && break
|
|
done
|
|
fi
|
|
|
|
# Get partition table type
|
|
ptable=$(blkid -p -s PTTYPE "$dev_path" 2>/dev/null | grep -oP 'PTTYPE="\K[^"]+')
|
|
[[ -z "$ptable" ]] && ptable="none"
|
|
|
|
# Get initial mount point
|
|
mount_point=$(findmnt -no TARGET "$dev_path" 2>/dev/null | head -1)
|
|
if [[ -z "$mount_point" && -n "$luks_mapper" ]]; then
|
|
mount_point=$(findmnt -no TARGET "/dev/mapper/$luks_mapper" 2>/dev/null | head -1)
|
|
fi
|
|
|
|
# Get HBA information
|
|
hba_info=""
|
|
if [[ -L "/sys/block/$device" ]]; then
|
|
dev_path_sys=$(readlink -f "/sys/block/$device")
|
|
|
|
# Exclude USB, virtual, and NVMe devices from HBA detection
|
|
if [[ ! "$dev_path_sys" =~ (usb|virtual|nvme) ]]; then
|
|
phy=$(echo "$dev_path_sys" | grep -oP 'phy-\K[0-9]+' | head -1)
|
|
port=$(echo "$dev_path_sys" | grep -oP 'port-\K[0-9]+' | head -1)
|
|
target=$(echo "$dev_path_sys" | grep -oP 'target\K[0-9:]+' | head -1)
|
|
|
|
# Find the actual storage controller in the PCI chain
|
|
mapfile -t pci_addrs < <(echo "$dev_path_sys" | grep -oP '\d+:\d+:\d+\.\d+')
|
|
for addr in "${pci_addrs[@]}"; do
|
|
desc=$(lspci -s "$addr" 2>/dev/null | cut -d: -f3-)
|
|
if [[ "$desc" =~ (SAS|SATA|RAID|HBA|LSI|Adaptec|AHCI) ]]; then
|
|
pci_addr="$addr"
|
|
pci_desc="$desc"
|
|
break
|
|
fi
|
|
done
|
|
|
|
# Build HBA info string
|
|
if [[ -n "$pci_addr" ]]; then
|
|
hba_info="PCI: $pci_addr ($pci_desc)"
|
|
[[ -n "$phy" ]] && hba_info="$hba_info | PHY: $phy"
|
|
[[ -n "$port" ]] && hba_info="$hba_info | Port: $port"
|
|
[[ -n "$target" ]] && hba_info="$hba_info | Target: $target"
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
# Get Btrfs information
|
|
btrfs_label=""
|
|
btrfs_uuid=""
|
|
btrfs_devid=""
|
|
|
|
# Check device or its LUKS mapper for btrfs
|
|
check_dev="$dev_path"
|
|
if [[ -n "$luks_mapper" ]]; then
|
|
check_dev="/dev/mapper/$luks_mapper"
|
|
fi
|
|
|
|
btrfs_show=$(btrfs filesystem show "$check_dev" 2>/dev/null)
|
|
if btrfs filesystem show "$check_dev" &>/dev/null; then
|
|
btrfs_label=$(echo "$btrfs_show" | head -1 | grep -oP "Label: '\K[^']+")
|
|
btrfs_uuid=$(echo "$btrfs_show" | head -1 | grep -oP "uuid: \K[a-f0-9-]+")
|
|
btrfs_devid=$(echo "$btrfs_show" | grep -E "(${check_dev}|${dev_path})" | grep -oP "devid\s+\K[0-9]+" | head -1)
|
|
|
|
# If not mounted, check if any other device in the btrfs array is mounted
|
|
if [[ -z "$mount_point" && -n "$btrfs_uuid" ]]; then
|
|
all_devs=$(echo "$btrfs_show" | grep "path" | grep -oP "path \K[^ ]+")
|
|
for btrfs_dev in $all_devs; do
|
|
mount_point=$(findmnt -no TARGET "$btrfs_dev" 2>/dev/null | head -1)
|
|
[[ -n "$mount_point" ]] && break
|
|
done
|
|
fi
|
|
fi
|
|
|
|
# Default mount point if still empty
|
|
[[ -z "$mount_point" ]] && mount_point="Not mounted"
|
|
|
|
# Text output
|
|
echo "╔════════════════════════════════════════╗"
|
|
echo "║ Device: $dev_path"
|
|
echo "╚════════════════════════════════════════╝"
|
|
echo "Model: $model"
|
|
echo "Serial: $serial"
|
|
echo "WWN: $wwn"
|
|
echo "Size: $size"
|
|
echo "Rotation: $rpm"
|
|
echo "Form Factor: $form_factor"
|
|
echo "Interface: $interface"
|
|
echo "Disk ID: $disk_id"
|
|
echo "Filesystem UUID: $uuid"
|
|
echo "LUKS UUID: $luks_uuid"
|
|
echo "Partition Table: $ptable"
|
|
echo "Mount: $mount_point"
|
|
echo "HBA Info: $hba_info"
|
|
echo "SMART Health: $smart_health"
|
|
echo "Temperature: $temp"
|
|
echo "Power On Hours: $power_hours"
|
|
echo "Btrfs Label: $btrfs_label"
|
|
echo "Btrfs UUID: $btrfs_uuid"
|
|
echo "Btrfs devid: $btrfs_devid"
|
|
echo
|
|
done |