Hello,
I use a bunch of STEC ssd. They are old but runs good and have high endurance. Regular smartctl doesn't return all needed information. Proxmox GUI show wearout as N/A.
To get more information I use #sdmcmd64
In Diskmanage.pm get_wear_leveling_info try to detect from regular smart fields but STEC have different.
To read only estimatedRemainingLifePercentage AI generated this
Python:
Perl:
How could it be possible to integrate and show wearout in GUI ?
I use a bunch of STEC ssd. They are old but runs good and have high endurance. Regular smartctl doesn't return all needed information. Proxmox GUI show wearout as N/A.
To get more information I use #sdmcmd64
In Diskmanage.pm get_wear_leveling_info try to detect from regular smart fields but STEC have different.
Code:
./sdmcmd64 GetState target=gen4sas:Drive0
Results for GetState
operationResult = Success
target = gen4sas:Drive0
deviceState = Ready
percentDone = 100 0x64
smartReadErrorsRate = 0 0x0
smartReadErrorsExceeded = false
smartWriteErrorsRate = 0 0x0
smartWriteErrorsExceeded = false
smartEccCorrectionRate = 0 0x0
smartEccCorrectionExceeded = false
smartEraseErrorRate = 0 0x0
smartEraseErrorExceeded = false
smartTemperature = 44 0x2c
smartTemperatureExceeded = false
smartFreeBlocksPercentage = 94 0x5e
smartFreeBlocksPercentageExceeded = false
smartPowerOnHours = 48169 0xbc29
smartPowerCycleCount = 128 0x80
smartPowerBackupConditionFault = false
smartRomCheckFault = false
smartWrongFirmwareFault = false
smartFlashDieMoreThanHalfBadFault = false
smartReadErrorRateThreshold = 10 0xa
smartWriteErrorRateThreshold = 10 0xa
smartEccCorrectionThreshold = 80 0x50
smartEraseErrorRateThreshold = 10 0xa
smartTemperatureThreshold = 75 0x4b
smartLowFreepagesThreshold = 10 0xa
estimatedRemainingLifePercentage = 95 0x5f
estimatedRemainingLifeThreshold = 5 0x5
estimatedRemainingLifeExceeded = false
highestEraseCount = 1786
To read only estimatedRemainingLifePercentage AI generated this
Python:
Python:
#!/usr/bin/env python3
"""
Usage: ssd_life.py /dev/sdX
Prints only the estimatedRemainingLifePercentage value (e.g. "94").
"""
import sys
import subprocess
LOG_SENSE_PAGE_0x34_CDB = ["4d", "00", "74", "00", "00", "00", "00", "00", "c8", "00"]
PARAM_ID_REMAINING_LIFE = 0xE9
def get_remaining_life(dev: str) -> int:
# -b/--binary: sg_raw writes raw response bytes to stdout instead of a
# formatted hex dump. Status messages ("SCSI Status: Good", etc.) still
# go to stderr, so capture_output keeps them separate from stdout.
result = subprocess.run(
["sg_raw", "-b", "-r", "200", dev, *LOG_SENSE_PAGE_0x34_CDB],
capture_output=True,
check=True,
)
data = result.stdout
for i in range(4, len(data) - 7, 8):
if data[i] == PARAM_ID_REMAINING_LIFE:
return data[i + 2]
raise RuntimeError("remaining-life parameter (0xE9) not found in log page 0x34")
if __name__ == "__main__":
if len(sys.argv) != 2:
sys.stderr.write(f"Usage: {sys.argv[0]} /dev/sdX\n")
sys.exit(1)
disk = sys.argv[1]
try:
print(get_remaining_life(disk))
except subprocess.CalledProcessError as e:
sys.stderr.write(f"sg_raw failed: {e.stderr.decode(errors='replace')}\n")
sys.exit(2)
except Exception as e:
sys.stderr.write(f"Error: {e}\n")
sys.exit(3)
Perl:
Perl:
#!/usr/bin/perl
#
# Usage: ssd_life.pl /dev/sdX
# Prints only the estimatedRemainingLifePercentage value (e.g. "94").
use strict;
use warnings;
my @CDB = qw(4d 00 74 00 00 00 00 00 c8 00); # LOG SENSE, page 0x34
my $PARAM_ID_REMAINING_LIFE = 0xE9;
if (@ARGV != 1) {
print STDERR "Usage: $0 /dev/sdX\n";
exit 1;
}
my $dev = $ARGV[0];
# -b/--binary: write raw binary bytes to stdout instead of a hex dump
# sg_raw also prints "SCSI Status: Good" / "Writing N bytes..." to stderr;
# use a shell pipeline so we can redirect that away and keep stdout clean.
my $cmd = join(" ", "sg_raw", "-b", "-r", "200", quotemeta($dev), @CDB, "2>/dev/null");
open(my $fh, "-|", $cmd) or do {
print STDERR "Could not run sg_raw: $!\n";
exit 2;
};
binmode $fh;
local $/;
my $data = <$fh>;
close $fh;
if ($? != 0) {
print STDERR "sg_raw failed (exit code " . ($? >> 8) . ")\n";
exit 2;
}
my $len = length($data // '');
my $found;
for (my $i = 4; $i <= $len - 8; $i += 8) {
my $param_id = ord(substr($data, $i, 1));
if ($param_id == $PARAM_ID_REMAINING_LIFE) {
$found = ord(substr($data, $i + 2, 1));
last;
}
}
if (!defined $found) {
print STDERR "remaining-life parameter (0xE9) not found in log page 0x34\n";
exit 3;
}
print "$found\n";
How could it be possible to integrate and show wearout in GUI ?