sg_write_x can dry-run a SCSI write, checking your input and block range before anything touches the disk. A successful dry-run does not write media, but the real write remains your responsibility. Allow about 20 minutes for a first test.
/dev/zero, and a SCSI device whose capacity and write behaviour you understand.sudo only after reviewing the complete command.Start with read-only commands. This host has package version 1.46-3ubuntu4, while the executable reports its own upstream version as 1.24 from 20200429. The installed manpage identifies itself as sg3_utils-1.45.
$ command -v sg_write_x
/usr/bin/sg_write_x
$ dpkg-query -W -f='${Package} ${Version}\n' sg3-utils
sg3-utils 1.46-3ubuntu4
$ sg_write_x --version
sg_write_x version: 1.24 20200429
That mismatch is a reason to trust the local help and manpage together, not to copy an option from a different release without checking it. --help is also worth reading: it confirms that this build accepts long options such as --atomic, --same, --scattered and --stream, and it shows a few short-option spellings that differ from the long option's first letter, so prefer the long form in scripts and runbooks.
Checkpoint: Record the device path, package version and executable version before changing anything.
sg_write_x sends one of six SCSI commands: normal WRITE, ORWRITE, WRITE ATOMIC, WRITE SAME, WRITE SCATTERED or WRITE STREAM. If no variant is selected, normal WRITE is assumed unless --strict requires an explicit choice. The default CDB is the 16-byte form; --32 selects the 32-byte form, but all 32-byte variants except ORWRITE(32) require suitable type 1, 2 or 3 protection information formatting on the device.
For a first test, choose normal WRITE or WRITE ATOMIC deliberately. Atomic writing is not a generic safety switch: it asks the device to provide the atomic behaviour described by its SCSI implementation. This is a representative four-block WRITE ATOMIC request, not a command to paste against an unknown disk:
sudo sg_write_x --atomic=0 --bs=512 --in=/dev/zero \
--lba=0x1234 --num=4 /dev/sgX
Replace /dev/sgX with the correct device, and verify the LBA independently. The hexadecimal LBA is accepted by the utility. With a 512-byte block size, this command supplies 2048 bytes of zeroes, targeting blocks 0x1234 through 0x1237 inclusive.
Do not leave out --lba while experimenting. The manpage says its default is logical block 0. The default block count is zero, which is harmless, but adding a real input file and forgetting the intended LBA is not a useful safety strategy.
--bs? The utility asks the device for its block size with READ CAPACITY(16), then tries READ CAPACITY(10) if needed. Convenient for a known device, but it is another device operation to understand during a test.--num counts logical blocks, not bytes. The utility attempts to read the actual block size multiplied by the block count from --in.--strict is absent, missing bytes are replaced with zeroes. Add --strict so a short or malformed input stops before the SCSI write:sudo sg_write_x --normal --strict --bs=512 \
--in=/path/to/payload.bin --lba=0x1234 --num=4 /dev/sgX
Here payload.bin must provide at least 2048 bytes. The command still writes only after all checks pass, so --strict is a guard against accidental padding, not a preview.
--dry-run exits immediately before sending the selected write CDB. It may still issue READ CAPACITY and it still reads and processes the input file. It also performs command-line and sanity checks. This makes it the right checkpoint before a real write, but it is not a virtual device and it does not prove that the target would accept the write.
sudo sg_write_x --atomic=0 --strict --dry-run --bs=512 \
--in=/dev/zero --lba=0x1234 --num=4 /dev/sgX
$ printf 'dry-run status: %s\n' "$?"
dry-run status: 0
A zero status means the command reached the point immediately before the write. It does not confirm the target's atomic support, protection information, write permissions or final media result. If the device cannot answer capacity commands, try an explicit correct --bs, but do not use that to conceal an unknown device format.
Checkpoint: Stop here and compare the device path, variant, CDB size, block size, LBA, count and input length with your change record.
--same=0 selects WRITE SAME with a data-out buffer. --same=1 sets NDOB, meaning no data-out buffer, and ignores data-buffer options.--unmap sets the UNMAP and ANCHOR bits for WRITE SAME: 1 means UNMAP, 2 means ANCHOR and 3 means both. Treat these as destructive media-management operations, not a convenient way to fill a disk.--stream=ID selects WRITE STREAM and --or selects ORWRITE.--scattered=RD sends WRITE SCATTERED, where comma-separated LBA and block-count lists must have matching lengths. A scatter file can replace those lists, but its ASCII format and the binary --scat-raw format are different. Begin with a small, explicit list: the combined-buffer mode is easy to miscalculate and can place unintended data on several ranges.For any of these variants, add --strict while testing, and --verbose when diagnostics matter. Keep --timeout in mind: the default is 120 seconds, and a large request on slow media may need longer. A longer timeout does not make a write safer.
Warning: The next command changes the contents of the target. It can overwrite useful data, trigger device-specific protection behaviour, or disrupt a service using the logical unit. Unmount filesystems and stop dependent services only when that is part of your storage procedure. Keep a recovery plan; there is no general undo command for a SCSI block write.
Once the dry-run and review agree, remove only --dry-run from the exact command you tested. Keep --strict and the explicit block size:
sudo sg_write_x --atomic=0 --strict --bs=512 \
--in=/path/to/payload.bin --lba=0x1234 --num=4 /dev/sgX
$ printf 'write status: %s\n' "$?"
write status: 0
Zero is the utility's successful exit status. It means the command completed successfully according to the device and operating system, not that your higher-level data or application has been validated. A non-zero result needs the diagnostic on standard error, the SCSI sense information and the device documentation. Do not rerun a failed write blindly: a timeout can leave the device in an uncertain state.