Chrony Tracking in Milliseconds

If you are running NTP server based on Chrony, you are probably checking its status too. For me chronyc tracking has been almost perfect. The only thing I dislike is having seconds in outputs. For any decent NTP server, these values are sub-millisecond and thus output has a lot of zeros.

Fortunatelly, changing seconds to milliseconds is easy:

chronyc tracking | awk '
  /seconds/ {
    sub(/seconds/, "milliseconds")
    for (I=1; I<=NF; I++) {
      if ($I ~ /^[+-]?[0-9.]+$/) {
        $I = sprintf("%.6f", $I * 1000)
      }
    }
  } { print }'

This awk command will match any line that has word seconds with milliseconds and then multiply any number it finds with 1000. Once printed again, this means all numbers are in milliseconds, just as we wanted.

This does work but it will also adjust Update interval, which is one field that makes sense to be in seconds. So, we can limit how many changes are to be done.

chronyc tracking | awk '
  /seconds/ && count < 5 {
    sub(/seconds/, "milliseconds")
    for (I=1; I<=NF; I++) {
      if ($I ~ /^[+-]?[0-9.]+$/) {
        $I = sprintf("%.6f", $I * 1000)
      }
    }
    count++
  } { print }'

Here we just add counter to limit our changes to only the first 5 fields. Since chronyc tracking output is relatively stable, we got to “cheat” a bit.

If you’re using this as input for something else, this is sufficient. However, if you plan to look at it on the command line, you will notice that changed lines also had their spaces messed up. For that, here is the final form.

chronyc tracking | awk '
  /seconds/ && count < 5 {
    sub(/seconds/, "milliseconds")
    for (I=1; I<=NF; I++) {
      if ($I ~ /^[+-]?[0-9.]+$/) {
        $I = sprintf("%.6f", $I * 1000)
      }
    }
    count++
  } { print }' | awk '{
    sub(/:/, "\t")
    print
  }' | column -t -s$'\t' -o:

Here we make use of the column command to make a nice table using tab (\t) as an input and colon (:) as output separator. Reason we cannot use colons for input separation lies in ref time field which includes colons in the time string. So, in order for this to work, we also adjust input to column by replacing the first colon with tab and leaving the rest intact.

Now your output should look something like this:

Reference ID    : 81060F1C (time-a-g.nist.gov)
Stratum         : 2
Ref time (UTC)  : Sun May 24 00:00:01 2026
System time     : 0.207166 milliseconds fast of NTP time
Last offset     : 0.010373 milliseconds
RMS offset      : 0.052737 milliseconds
Frequency       : 23.102 ppm slow
Residual freq   : +0.000 ppm
Skew            : 0.006 ppm
Root delay      : 24.370797 milliseconds
Root dispersion : 1.106555 milliseconds
Update interval : 1033.8 seconds
Leap status     : Normal