Read and Set a SCSI Device Timestamp with sg_timestamp
You will finish with a repeatable way to read the timestamp held by a SCSI device, turn it into a human-readable date, inspect how that clock was initialised, and set it when the device requires it. The examples use sg_timestamp 1.14 (20191220), supplied here by sg3-utils 1.46-3ubuntu4.
The route
Jump straight to the step you need, or tick off Done means at the end.
Allow about fifteen minutes. You need a Linux shell, the sg3-utils package, and the correct SCSI device path. Reading a device may need access to its device node. Setting its timestamp changes device state and may need elevated privileges. Do not experiment with a disk that is handling production I/O.
1. Confirm the installed command
Check the executable, package and version before relying on examples. These are ordinary, read-only commands:
$ command -v sg_timestamp
/usr/bin/sg_timestamp
$ dpkg-query -W -f='${Package} ${Version}\n' sg3-utils
sg3-utils 1.46-3ubuntu4
$ sg_timestamp --version
version: 1.14 20191220
Option names and output can vary between releases. This guide follows the installed command and its local sg_timestamp(8) manual. If your version reports different help, use that help as the final authority for your host.
Checkpoint
You have confirmed that sg_timestamp is installed and know which device path you intend to inspect.
2. Read the timestamp without changing it
Without a set option, the program sends SCSI REPORT TIMESTAMP. Add --readonly so the device is opened read-only, and use --srep to ask for Unix-style seconds rather than the device's native milliseconds:
$ sg_timestamp --readonly --srep /dev/sgX
1448993950
Replace /dev/sgX with the generic SCSI device node for your target. Do not guess it from a partition name. Identify the device with your normal storage inventory first, then check the path exists:
$ test -c /dev/sgX && echo 'device node exists'
device node exists
The number is seconds since 1970-01-01 00:00:00 UTC. A successful command prints one value and exits with status 0. A device that does not implement REPORT TIMESTAMP will return an error instead; adding sudo cannot add a SCSI feature that the device lacks.
3. Convert the value to a date
GNU date accepts an epoch value with --date=@.... Keep the command substitution separate so the value can be checked before it is displayed:
$ timestamp=$(sg_timestamp --readonly --srep /dev/sgX) && printf 'device seconds: %s\n' "$timestamp"
device seconds: 1448993950
$ date --date="@$timestamp"
Tue Dec 1 18:19:10 GMT 2015
$ date --date="@$timestamp" --rfc-email
Tue, 01 Dec 2015 18:19:10 +0000
Your local time zone changes the displayed clock time. The stored value is still UTC-based. For a script, test the exit status of sg_timestamp and validate that a value was returned before passing it to another command. Do not silently treat an empty result as the current time.
If you need the native representation, omit --srep. The report then prints milliseconds since the same epoch. The --milliseconds set option uses that unit too.
4. Inspect the timestamp origin
The report contains a timestamp origin field, but the normal output does not print it. Add --origin to decode it:
$ sg_timestamp --readonly --origin --srep /dev/sgX
timestamp origin: power up or hard reset
1448993950
The descriptive form identifies the most recent event that initialised the device clock. The manual defines value 0 as power-up or hard-reset initialisation, value 2 as a previous SET TIMESTAMP operation, and value 3 as another method. Use --origin twice when you need the numeric field, or three times for a machine-readable line:
$ sg_timestamp --readonly --origin --origin --origin --no-timestamp /dev/sgX
TIMESTAMP_ORIGIN=2
--no-timestamp is useful here because it suppresses the timestamp value and leaves the origin line as the result to parse. Check your installed help if you build a parser around other verbosity or diagnostic output.
5. Save the old value before making a change
Setting the timestamp sends SCSI SET TIMESTAMP. It changes state in the device, not merely the output of this command. Before doing it, capture the current value so you have an exact recovery value:
$ old_seconds=$(sg_timestamp --readonly --srep /dev/sgX) && printf 'saved old value: %s\n' "$old_seconds"
saved old value: 1448993950
Warning
Changing a shared device clock can affect logs, utilisation records and vendor-specific features that use timestamps. Stop any operation that depends on the device and follow its maintenance procedure first. This command does not set the Linux host clock.
6. Set the device timestamp to now
Use --seconds with the current Unix time when the device expects second precision:
$ now=$(date +%s) && sudo sg_timestamp --seconds="$now" /dev/sgX
$ sudo sg_timestamp --readonly --srep /dev/sgX
1760000000
The second output is illustrative: it will be close to the value generated by date when you run the command. The program multiplies --seconds by 1000 before sending SET TIMESTAMP. Use --milliseconds=MS instead when you have a specific millisecond value to apply. The two set options are mutually exclusive.
Elevated privileges are only one possible requirement. The device, transport and enclosure may also reject SET TIMESTAMP. Treat a non-zero exit status as a failed change and inspect the device's error message.
7. Verify or recover the change
Read the value back after a successful set. Allow for the small delay between generating now and reading the device:
$ sudo sg_timestamp --readonly --srep /dev/sgX
1760000001
$ date --date="@1760000001" --rfc-email
Tue, 07 Oct 2025 08:53:21 +0000
If you need to undo the change, set the saved value explicitly. There is no general undo command because the previous timestamp is device-specific:
$ sudo sg_timestamp --seconds="$old_seconds" /dev/sgX
$ sudo sg_timestamp --readonly --srep /dev/sgX
1448993950
If the shell that holds old_seconds has ended, recover the value from your maintenance record. Do not use the current host time as an undo value unless that is genuinely the intended device time.
8. Handle useful diagnostics safely
Use --hex when you need the raw REPORT TIMESTAMP response in hexadecimal on standard error, or --raw when another program needs the binary response on standard output. Raw mode is not human-readable, ignores --origin and --srep, and sends diagnostics to standard error. Redirect it to a named file only when you have confirmed the destination will not overwrite useful data.
--elapsed formats a reported value as days, hours, minutes, seconds and milliseconds. That is appropriate when the device value represents elapsed time since an event such as a power cycle, not when you want a calendar date. Do not apply both interpretations to the same output.
Done means
- You confirmed the installed
sg_timestampandsg3-utilsversions. - You read the device with
--readonlyand selected seconds or milliseconds deliberately. - You converted the result with the correct UTC epoch interpretation.
- You inspected timestamp origin when the device history mattered.
- You saved the old value before a state-changing SET TIMESTAMP operation.
- You read the value back, and you know how to restore the saved value.