Read SCSI Target Port Groups Safely with sg_rtpg
A path silently stops taking traffic on a multipath array, and sg_rtpg is how you check which target port group each path is actually in. It sends the SCSI REPORT TARGET PORT GROUPS command to a suitable device, reads back the access-state response, and lets you pick an output format that suits a person or a script. Give it fifteen minutes.
The route
Jump straight to the step you need, or tick off Done means at the end.
- What you need: a Linux host with
sg3-utils, a SCSI device you are authorised to query, and enough privilege to open its device node. - What it will not touch: paths, reservations, target-port settings or multipath policy. This guide only reads device state.
- Versions used here:
sg3-utils1.46-3ubuntu4; the binary itself reportssg3_utils version 1.27 20180628. Note both if you ever compare hosts.
1. Confirm the installed command
Start with ordinary, read-only checks. They do not need a SCSI device or elevated privileges:
$ command -v sg_rtpg
/usr/bin/sg_rtpg
$ dpkg-query -W -f='${Package} ${Version}\n' sg3-utils
sg3-utils 1.46-3ubuntu4
$ sg_rtpg --version
Version: 1.27 20180628
Package version and utility version are separate facts, and they can drift apart, so record both when comparing hosts. The local manpage is dated May 2014 and describes the same option set shown by the installed help output.
Checkpoint
If command -v finds nothing, stop and install or repair the package through your normal operating-system process. Do not copy a binary from another host just to make this check work.
2. Identify a real SCSI device
Set a shell variable to the device node you have been given. A SCSI generic node such as /dev/sg3, a block device such as /dev/sdb, or another supported SCSI device path may be appropriate on your host. Do not guess the number:
$ DEVICE='/dev/sgX'
$ test -e "$DEVICE" && printf 'device exists: %s\n' "$DEVICE"
device exists: /dev/sgX
Replace /dev/sgX with the actual path before running the query. That placeholder is deliberately not a copy-and-paste target. The sg3_utils project documents both SCSI generic nodes and, on modern Linux systems, many primary device names as valid inputs, but the device and transport must still support SCSI pass-through.
Before asking for target-port groups, check whether the device advertises the feature. The sg_rtpg(8) manpage points to sg_inq for viewing the standard INQUIRY response and says the command should be supported when the TPGS bits are greater than zero:
$ sg_inq "$DEVICE"
# inspect the standard INQUIRY response for TPGS support
The exact response is device-specific. Treat an absent or zero TPGS value as a reason to stop and ask the storage administrator, not a reason to keep retrying the command.
3. Run the first query read-only
Use --readonly for the initial query:
$ sg_rtpg --readonly "$DEVICE"
# target port group descriptors are printed here
$ status=$?
$ printf 'sg_rtpg exit status: %s\n' "$status"
sg_rtpg exit status: 0
- Exit status 0 means success. The output holds the REPORT TARGET PORT GROUPS response, but its contents depend on the array, enclosure, target and current path state, so do not expect a fixed number of groups or a fixed access state.
- Read-only is an opening mode, not a magic fix. It controls how the device node is opened, using the Unix read-only mode. It does not turn an unsuitable device into a suitable one, and it does not grant access to a user who cannot open the node.
Safety warning
The default is to open DEVICE read-write. Do not omit --readonly in a script unless you have checked the device access requirements and have a specific reason to use the default. The SCSI command is an enquiry, but opening a storage device read-write is still an avoidable risk.
4. Decode the access state for people
For an operator-facing report, add --decode:
$ sg_rtpg --readonly --decode "$DEVICE"
# each returned target port group includes decoded status and
# asymmetric access state
Without --decode, those status and asymmetric-access values stay undecoded. Adding it just makes the result easier to read; it does not select a preferred path, switch an array controller or repair a failed port.
Keep the raw response when you need to preserve evidence for later analysis. The next command writes binary response data to standard output, so redirect it to a file rather than a terminal:
$ sg_rtpg --readonly --raw "$DEVICE" > rtpg-response.bin
$ status=$?
$ printf 'sg_rtpg exit status: %s\n' "$status"
sg_rtpg exit status: 0
rtpg-response.bin is a local evidence file, not a text report. Protect it under your storage and incident-handling rules, and check the exit status before treating it as usable: a failed command can still leave an empty or partial file behind.
5. Choose hex or extended output deliberately
Use --hex when you want the response in hexadecimal rather than partially or fully decoded output:
$ sg_rtpg --readonly --hex "$DEVICE"
# hexadecimal response is printed here
Use --extended to request the extended header format for the parameter data. This sets the PARAMETER DATA FORMAT field in the command. It is a protocol choice, not a display preference:
$ sg_rtpg --readonly --extended --decode "$DEVICE"
# decoded response using the extended header format
If you are comparing output with a storage vendor or a test case, record which of these options you used. Comparing a decoded default response against an extended-format one can send you chasing a difference your own command line created.
6. Investigate failures without changing storage state
First rerun the exact command with --verbose and capture its status:
$ sg_rtpg --readonly --verbose "$DEVICE" > rtpg.out 2> rtpg.err
$ status=$?
$ printf 'sg_rtpg exit status: %s\n' "$status"
sg_rtpg exit status: 0
Replace the shown success with whatever status you actually get. Non-zero means the command failed; the general sg3_utils(8) documentation describes the shared exit-status conventions. Read the diagnostic text in rtpg.err, confirm that DEVICE is the intended path, and check permissions and SCSI pass-through support.
Common traps
- Using a placeholder path. Copy-pasting
/dev/sgXunchanged queries nothing real. - Querying a device with zero TPGS bits. It never supported this command.
- Lacking permission to open the node. Check ownership and group before assuming a transport fault.
- Assuming a block device and its underlying SCSI generic node behave identically. They can differ.
Ask the storage owner before changing device permissions or retrying against another path. Do not reach for a reset, failover or multipath command as a response to an informational query failure.
There is no undo step for the commands in this guide: they query the device and leave no persistent configuration change. Remove any evidence files when your retention rules allow it:
$ rm -- rtpg-response.bin rtpg.out rtpg.err
Only remove files you created for this check. The command never creates or removes storage paths itself.
Done means
- Versions recorded. You noted the installed package and utility versions.
- Real device confirmed. You used the real, authorised SCSI device path rather than a placeholder.
- TPGS checked. You confirmed support and ran the first query with
--readonly. - Output chosen deliberately. Decoded, hexadecimal, raw or extended, for a stated reason.
- Exit status captured. Any binary response was kept separate from terminal output.