Inventory and Decode SCSI LUNs with sg_luns
sg_luns is your read-only way to list the logical units visible through a SCSI device. It also asks for well-known LUNs, decodes T10 LUN values, and translates them to Linux integers. The installed command is from sg3-utils 1.46-3ubuntu4. The local manpage identifies its interface as sg3_utils 1.45, so output details can differ on newer builds.
The route
Jump straight to the step you need, or tick off Done means at the end.
Allow about fifteen minutes. You need the sg3-utils package and a SCSI generic device such as /dev/sg1. You must have access to the target, and the target must support REPORT LUNS. The examples that use --test are safe on any machine because they decode a value and do not open a device. Device mode sends a SCSI command, so use it during a suitable maintenance window if the target is sensitive.
1. Check the installed command
Confirm the package and binary before relying on option details. These are ordinary read-only commands and do not need elevated privileges:
$ dpkg-query -W -f='${Package} ${Version}\n' sg3-utils
sg3-utils 1.46-3ubuntu4
$ sg_luns --version
version: 1.45 20200708
The package version and utility version are not the same string here. Record both when comparing output between hosts. Check the local option spelling if a distribution has backported changes:
$ sg_luns --help
Checkpoint
You have a working binary and know which version produced your notes.
2. Decode a LUN without touching hardware
Use test mode when you already have a hexadecimal T10 LUN and only need to understand it. This command ignores the device argument because it is not sending REPORT LUNS:
$ sg_luns --test=0002000000000000
Decoded LUN:
Peripheral device addressing: lun=2
The value can be prefixed with 0x, grouped with hyphens, or quoted when spaces separate bytes. A shorter hexadecimal value is padded to the right to make a 64-bit LUN. Ask for component fields in hexadecimal with --hex:
$ sg_luns --test=0x023a004b --hex
Decoded LUN:
Peripheral device addressing: bus_id=0x02, target=0x3a
>>Second level addressing:
Peripheral device addressing: lun=0x4b
Do not confuse the option with a request to query a device. --test is a decoder and is the best first step when investigating a value copied from logs.
3. Translate between T10 and Linux LUN forms
Linux uses a word-flipped integer representation for some LUN work. Prefix a decimal Linux value with L to convert it to T10 format:
$ sg_luns --test=L49409
64 bit LUN in T10 preferred (hex) format: c1 01 00 00 00 00 00 00
Decoded LUN:
REPORT LUNS well known logical unit
For the reverse conversion, put a trailing L on the hexadecimal value:
$ sg_luns --test=c101L
Linux 'word flipped' integer LUN representation: 49409
Decoded LUN:
REPORT LUNS well known logical unit
The letter L has meaning only in this test-mode syntax. It is not a general shell option and it does not identify a Linux block device.
4. Query the target's ordinary LUN inventory
Find the correct SCSI generic node first. On Linux, lsscsi -g can show the generic device beside each SCSI logical unit:
$ lsscsi -g
[6:0:0:1] disk Linux scsi_debug 0004 /dev/sdb /dev/sg1
Use the generic node that represents the target you intend to inspect. Device mode opens it read-write by default, although REPORT LUNS is an inventory command. Add --readonly to request a read-only open:
$ sg_luns --readonly --quiet /dev/sg1
0001000000000000
0002000000000000
--quiet removes the explanatory header and prints one ASCII-hex LUN per line, which is easier to feed into a review script. Without it, expect a report length and a selected-report header before the values. A successful command exits with status 0.
Safety boundary
Replace /dev/sg1 only with the verified device node. Do not point this command at a storage device selected by guesswork, and do not use --raw in a terminal: it writes binary response data to standard output.
5. Select the report you actually need
The default selection is 0, which reports LUNs apart from well-known logical units. Use selection 1 to ask only for well-known units:
$ sg_luns --readonly --quiet --select=1 /dev/sg1
c101000000000000
Use selection 2 for all LUNs visible to the current I_T nexus:
$ sg_luns --readonly --quiet --select=2 --decode --linux /dev/sg1
0001000000000000 [1]
Peripheral device addressing: lun=1
0002000000000000 [2]
Peripheral device addressing: lun=2
c101000000000000 [49409]
REPORT LUNS well known logical unit
The exact list is target-specific. Selection values 0x10, 0x11 and 0x12 have administrative meanings and device restrictions documented by the manpage. Do not try them merely to make a missing LUN appear: for 0x10 and 0x11 the device must be LUN 0 or the REPORT LUNS well-known LUN, and 0x12 requires an administrative LUN.
6. Handle failures without changing storage state
A missing or unsuitable generic node, permissions, an unsupported command, and an invalid selection can all produce a non-zero exit status. Capture it immediately instead of trusting partial output:
$ sg_luns --readonly --quiet /dev/sg1
$ status=$?
$ printf 'sg_luns exit status: %s\n' "$status"
sg_luns exit status: 0
If access is denied, check the node and its group membership first. Use sudo only when your host's device policy requires it:
$ ls -l /dev/sg1
$ sudo sg_luns --readonly --quiet /dev/sg1
Elevated privileges do not repair a wrong node or an unsupported target. If the response is truncated, increase --maxlen, whose default is 8192 bytes and maximum is 1048576:
$ sg_luns --readonly --quiet --maxlen=65536 /dev/sg1
Use --verbose for diagnostics. Treat a report as a snapshot: another administrator or a fabric change can alter the visible inventory after the command returns.
Done means
- Versions recorded. You recorded the installed package and utility versions.
- Decoding without hardware. You can decode a T10 value with
--testwithout contacting hardware. - Node verified. You verified the SCSI generic node before querying it.
- Read-only and deliberate. You used
--readonlyand selected 0, 1 or 2 deliberately. - Presentation versus binary. You know that
--quietchanges presentation, while--rawemits binary data. - Status checked. You checked the exit status and kept administrative selections out of routine discovery.