Inspect SCSI Element Status Safely with sg_get_elem_status

sg_get_elem_status asks a SCSI device for physical or storage element status and decodes the answer. The installed command here comes from package sg3-utils version 1.46-3ubuntu4. Its version output is 1.03 20200423, while the local manual page is labelled sg3_utils-1.45, so the examples below describe the command actually installed rather than assuming every release behaves the same.

Allow about fifteen minutes. You need a shell, sg3-utils, and a SCSI device that supports GET PHYSICAL ELEMENT STATUS. You may need elevated privileges to open the device node. This guide only reads status; nothing here alters element state, depopulates media, or changes a device configuration.

1. Check the installed command

Start with ordinary, read-only checks. They do not open a device and need no sudo:

$ command -v sg_get_elem_status
/usr/bin/sg_get_elem_status
$ sg_get_elem_status --version
version: 1.03 20200423
$ dpkg-query -W -f='\${Package} \${Version}\n' sg3-utils
sg3-utils 1.46-3ubuntu4

The program's option names show up in its own help output:

$ sg_get_elem_status --help
Usage: sg_get_elem_status  [--brief] [--filter=FLT] [--help] [--hex]
                           [--inhex=FN] [--maxlen=LEN] [--raw] [--readonly]
                           [--report-type=RT] [--starting=ELEM] [--verbose]
                           [--version] DEVICE

Checkpoint: confirm the path and package version match the host you are documenting. If another sg_get_elem_status appears earlier in PATH, chase that down before comparing output with this guide.

2. Identify the target without guessing

Replace /dev/sgX with the device node for the enclosure, disk shelf or other SCSI target you actually mean to inspect. Never substitute a random disk just because its name looks plausible. Use your normal inventory tools first, and record the exact path:

$ ls -l /dev/sgX
crw-rw---- 1 root disk 21, 0 ... /dev/sgX

Permissions here are host-specific. If the device is not readable by your account, either use the approved device-access group or run the final command with whatever privilege your system requires. Do not grant broad permissions just to make this diagnostic convenient.

Here is the fact that trips people up: the command opens a device read-write by default, even though GET PHYSICAL ELEMENT STATUS is only a status query. Use --readonly for the normal inspection path:

$ sg_get_elem_status --readonly /dev/sgX

On a real target, successful output contains a response header followed by decoded element status descriptors, with identifiers and status fields that depend on the enclosure or device. A placeholder path is not a test, so do not treat an error from /dev/sgX as evidence the command or protocol is broken.

3. Request enough response space

The command sends an allocation length in the SCSI command itself. If --maxlen is omitted, the local manual says the default is 32 bytes, enough for the response header but rarely enough for a useful list of descriptors. Give a larger value when you want element records, using a multiple of 32 such as 64 or 96:

$ sg_get_elem_status --readonly --maxlen=96 /dev/sgX

Pick a value that fits the target and the number of descriptors you expect. A larger allocation length does not create elements and does not guarantee the device returns more information; it only gives the response room to contain it. If you are chasing a device-specific limit, raise the value deliberately and compare the returned header and descriptor count.

Checkpoint: rerun the same command with a shell status check straight after:

$ sg_get_elem_status --readonly --maxlen=96 /dev/sgX
$ printf 'exit status: %s\n' "$?"
exit status: 0

Zero means the utility completed successfully. It does not mean every element is healthy. Read the decoded status fields against the device's documentation before turning a status value into an operational decision.

4. Select physical or storage elements

The default report type here is 1, storage elements. Request physical elements with --report-type=0:

$ sg_get_elem_status --readonly --report-type=0 --maxlen=96 /dev/sgX
$ sg_get_elem_status --readonly --report-type=1 --maxlen=96 /dev/sgX

These are different views of the same GET PHYSICAL ELEMENT STATUS command. The device may not support both usefully, and an unsupported or malformed request can produce a non-zero exit status. Keep the report type explicit in scripts so a future reader is not left guessing the default.

--starting=ELEM limits the response to physical elements whose identifiers are at least the supplied value. The documented default is zero, even though element identifiers themselves are never zero. For a targeted inspection:

$ sg_get_elem_status --readonly --report-type=0 --starting=32 --maxlen=96 /dev/sgX

The starting identifier filters the returned descriptors; it is not a slot number the command changes. For a complete inventory, leave the option out, or use the device's documented starting range.

5. Narrow the report when checking exceptions

The --filter value is a two-bit field. The default 0 asks for every element descriptor. Value 1 asks only for descriptors outside specification or carrying depopulation information:

$ sg_get_elem_status --readonly --filter=1 --maxlen=96 /dev/sgX

Report type and starting element still restrict the result, so an empty or short response does not prove the device has no physical problems. It just means no descriptors matched that particular combination of filters and response length.

Use --brief for less presentation around the decoded response, and --verbose for diagnostic output, which the manual says goes to standard error. Keep verbose output separate from normal records if another program will parse standard output.

6. Decode a captured response without touching hardware

For repeatable analysis, use --inhex with a file holding an ASCII-hex response already captured from this command. When --inhex is present, the device argument is ignored, and supplying one anyway triggers a warning:

$ sg_get_elem_status --inhex=/path/to/response.hex --maxlen=96 /dev/sgX

The file is read as ASCII hexadecimal by default. Add --raw when the input file is binary instead. With --inhex, --raw changes how the input file is read, not whether the decoded report itself is binary:

$ sg_get_elem_status --inhex=/path/to/response.bin --raw --maxlen=96 /dev/sgX

Keep captured responses protected if they reveal enclosure layout or serial-related data. Never put a live device path in an offline analysis script just because the option syntax accepts one: the offline path is useful precisely because it skips sending another SCSI command.

7. Diagnose failures without escalating blindly

A non-zero result can mean a missing device, insufficient permission, an unsupported command, malformed captured data, or a device-side SCSI error. Capture both output streams and the status together:

$ sg_get_elem_status --readonly --maxlen=96 /dev/sgX > element-status.txt 2> element-status.err
$ status=$?
$ printf 'exit status: %s\n' "$status"
$ sed -n '1,80p' element-status.err

Check the device path and access first. If permissions are the problem, use the approved administrative route and keep --readonly in place:

$ sudo sg_get_elem_status --readonly --maxlen=96 /dev/sgX

Elevated privileges add no SCSI support and repair no failing enclosure. Stop if the device carries production traffic and the error suggests a transport or hardware problem. Review the captured error with the storage administrator or vendor before firing off more requests.

Never point --raw at a terminal unless you deliberately want binary data on standard output. Redirect it to a file and inspect that file with a suitable tool, and avoid redirecting a new capture over an existing record: shell redirection truncates its destination before the command even starts.

Done means