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.

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

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

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