Home / Alt manpages / sg_decode_sense(8)

  • sg_decode_sense(8)
  • Admin command
  • linux

Decode SCSI Sense Bytes Safely with sg_decode_sense

sg_decode_sense turns a wall of hex from a kernel log into an actual sense key and error text you can act on. You can also identify a SCSI command descriptor block (CDB), decode a status byte and save a byte sequence for later inspection. Allow about ten minutes. The commands below only read or convert supplied data; none of them open a SCSI device.

This guide uses the installed sg3-utils package, version 1.46-3ubuntu4. On this machine, sg_decode_sense --version reports utility version 1.21 20190602, and that utility version is the one worth quoting, since package and utility version strings are not the same thing.

1. Confirm the tool and keep the raw bytes

First check the command is actually installed. No elevated privileges needed:

$ command -v sg_decode_sense
/usr/bin/sg_decode_sense
$ sg_decode_sense --version
version: 1.21 20190602

Copy the original log line somewhere safe before you start editing it. Sense data is usually shown as bytes beginning with 70, 71, 72, 73, f0 or f1. It can be as short as 18 bytes in the older fixed format, but the real data can run longer, so do not trim bytes just to make the line look tidier.

Checkpoint

The input should be hexadecimal bytes only, not the timestamp, device name or explanatory text around them. If you copied a whole kernel-log line, pull out just the byte sequence before running the decoder.

2. Decode bytes copied from a log

Pass space-separated hexadecimal bytes as positional arguments. This example is the fixed-format medium-error sample documented in the installed manual:

$ sg_decode_sense f0 00 03 00 00 12 34 0a 00 00 00 00 11 00 00 00 00 00
Fixed format, current; Sense key: Medium Error
Additional sense: Unrecovered read error
  Info fld=0x1234 [4660]

The sense key gives the broad class of failure; additional sense text narrows it down. Here the information field is 0x1234, decimal 4660. For this medium-error example the manual describes that field as the lowest logical block address the related command could not read, verify or write, but treat that as specific to this sense data, not a universal meaning for every SCSI response.

A successful decoder run exits with status zero. Check it immediately if a script is going to act on the result:

$ sg_decode_sense f0 00 03 00 00 12 34 0a 00 00 00 00 11 00 00 00 00 00 >/tmp/sg-sense.txt
$ printf '%s\n' "$?"
0

3. Read a longer or commented capture from a file

Use --file when the data spans several lines or you want to keep comments describing where it came from. The file holds ASCII hexadecimal, bytes separated by spaces, commas, tabs or newlines, and a hash character starts a comment to the end of that line:

$ cat > /tmp/sense-capture.txt <<'EOF'
# copied from the storage host log
f0 00 03 00 00 12 34 0a 00 00 00 00
11 00 00 00 00 00
EOF
$ sg_decode_sense --file=/tmp/sense-capture.txt
Fixed format, current; Sense key: Medium Error
Additional sense: Unrecovered read error
  Info fld=0x1234 [4660]

The here-document just creates a temporary input file; it does not touch system configuration. If the result differs from the command-line version, compare the bytes, separators and comment boundary. A common trap: a stray log prefix or leftover punctuation stuck to a byte.

For an unbroken hexadecimal string, use --nospace. It consumes two hex digits per byte, so it needs an even number of digits:

$ sg_decode_sense --nospace f00003000012340a000000001100000000
Fixed format, current; Sense key: Medium Error
Additional sense: Unrecovered read error
  Info fld=0x1234 [4660]

4. Decode a CDB or a SCSI status byte

A CDB is a command, not sense data. Add --cdb when you want the command name for a hexadecimal CDB:

$ sg_decode_sense --cdb 12 00 00 00 24 00
Inquiry

The decoder reads the first byte, the opcode, and sometimes a service-action field too. Never put --cdb on a sense-data command: it changes how every supplied byte is read.

A SCSI status byte is related to sense data but is not the same thing. Supply it in hexadecimal with --status:

$ sg_decode_sense --status=02
SCSI status: Check Condition

Check Condition usually means sense data is waiting to be examined too. The status byte alone never replaces the sense response.

5. Translate an sg3-utils exit status

When another utility in the package returns an exit status, --err prints the package's short description of that number. This is a separate action from decoding: every other decoder argument is ignored, apart from --verbose:

$ sg_decode_sense --err=5
Illegal request
$ sg_decode_sense --err=64
Bad address
$ sg_decode_sense --err=255
Utility returned 255 or higher

Use this for a human-readable label, not as a substitute for keeping the original numeric status. The program itself returns zero after printing the description, so a script that needs the real failure status has to save it before calling sg_decode_sense.

6. Save a converted copy without losing the source

--write writes the decoded input bytes to a named file. Without --hex the output is binary; with --hex it is ASCII hex formatted for a C compiler to consume:

$ sg_decode_sense --write=/tmp/sense.bin f0 00 03 00 00 12 34 0a 00 00 00 00 11 00 00 00 00 00
$ wc -c /tmp/sense.bin
18 /tmp/sense.bin
$ sg_decode_sense --hex --write=/tmp/sense.cbytes f0 00 03 00 00 12 34 0a 00 00 00 00 11 00 00 00 00 00
$ head -n 2 /tmp/sense.cbytes
0xf0,0x00,0x03,0x00,0x00,0x12,0x34,0x0a,0x00,0x00,0x00,0x00,0x11,0x00,0x00,0x00,0x00,0x00

Warning

An existing --write destination is truncated before the new data lands. Choose a new path or copy the old file first. The command creates the destination if it does not exist, so never point it at an original capture you still need: there is no undo, only restoring a backup or recapturing the bytes.

7. Handle the common mistakes

  • Invalid format or implausible fields: check every byte has exactly two hex digits and that you have not mixed a CDB in with sense data.
  • Output differs from expected: run the same bytes from a file so whitespace and comments become visible.
  • Using --nospace: count the digits and confirm the total is even.
  • Reaching for sudo: do not, just because the data came from a storage error. Decoding a copied byte string never touches a SCSI logical unit and needs no privilege; elevated access is a separate task for reading the original log or capturing new device data.

Keep the raw capture alongside the decoded text when escalating a storage fault. The readable phrase is useful for triage; the original bytes let another operator check the interpretation and inspect fields this version does not print.

Done means

  • Version checked before trusting the decoder's output.
  • Bytes preserved and decoded correctly as sense data, a CDB or a status byte, matching their actual type.
  • Right input mode used: a file or --nospace when the capture format called for it.
  • Write destination safe: new, or backed up before conversion.
  • No unnecessary privilege: decoder run without sudo, and the numeric status kept when using --err.