At some point in a Linux admins career they need to add timestamps to output. Whether it's logging for shell script or a simple command (like ping, traceroute, etc...) timestamps can come in handy. There are many ways to accomplish this, but none are as easy as the ts command. In this Linux quick tip we will show you how to easily add timestamps to any output using the ts command.

To use the ts command you must install the moreutils package.

Using the ts Command to Add Timestamps to Output

The basic function of the ts command is to add timestamps to the beginning of each line of input. The use of the word input is initially confusing, but it will become more clear as we go through examples.

If you call ts alone it will wait for input from the keyboard. Once it receives a line of input it will add a timestamp to the beginning of that line and print it to stdout (standard output). Here we are feeding input to ts on stdin (standard input).

[savona@putor ~]$ ts
This is a line of input from stdin
Feb 15 13:49:03 This is a line of input from stdin

NOTE: To learn more about standard streams (stdin/stdout/stderr), pipes, and redirection read "Linux Fundamentals - I/O, Standard Streams, and Redirection".

This becomes a lot more useful when you feed input from a pipe. In this example we will use the ts command to print timestamps on our ping output.

[savona@putor ~]$ ping 10.0.0.1 | ts
Feb 15 14:13:01 PING 10.0.0.1 (10.0.0.1) 56(84) bytes of data.
Feb 15 14:13:01 64 bytes from 10.0.0.1: icmp_seq=1 ttl=64 time=0.393 ms
Feb 15 14:13:02 64 bytes from 10.0.0.1: icmp_seq=2 ttl=64 time=0.380 ms
Feb 15 14:13:03 64 bytes from 10.0.0.1: icmp_seq=3 ttl=64 time=0.507 ms
Feb 15 14:13:04 64 bytes from 10.0.0.1: icmp_seq=4 ttl=64 time=0.381 ms

As you can see, ts added a timestamp to every line of input. You might ask, isn't that output? Yes, in the end it is output from the ts command. However, the pipe is taking the output from the ping command and sending it to ts as input.

The ts Command Options

There are only a few options for the ts command. Here we will outline some of these options and give examples.

Incremental Timestamps for Linux Output

Using the -s or -i options will give you incremental timestamps instead of absolute. However, they differ by the start of the incrementation.

The -s option will show incremental timestamps from the start of the program or action. In other words it will show the time since you started the program. Here you can see the ping example again, this time with incrementing timestamps.

[savona@putor ~]$ ping 10.0.0.1 | ts -s
00:00:00 PING 10.0.0.1 (10.0.0.1) 56(84) bytes of data.
00:00:00 64 bytes from 10.0.0.1: icmp_seq=1 ttl=64 time=0.359 ms
00:00:01 64 bytes from 10.0.0.1: icmp_seq=2 ttl=64 time=0.395 ms
00:00:02 64 bytes from 10.0.0.1: icmp_seq=3 ttl=64 time=0.412 ms
00:00:03 64 bytes from 10.0.0.1: icmp_seq=4 ttl=64 time=0.469 ms
00:00:04 64 bytes from 10.0.0.1: icmp_seq=5 ttl=64 time=0.460 ms

The -i options works a little differently. It shows the time since the last timestamp. In the past I have seen some shell scripts use this in very creative ways. Here is the ping example again, this time with incrementing timestamps showing the time since the last timestamp.

[savona@putor ~]$ ping -i 3 10.0.0.1 | ts -i
00:00:00 PING 10.0.0.1 (10.0.0.1) 56(84) bytes of data.
00:00:00 64 bytes from 10.0.0.1: icmp_seq=1 ttl=64 time=0.377 m
00:00:03 64 bytes from 10.0.0.1: icmp_seq=2 ttl=64 time=0.418 ms
00:00:03 64 bytes from 10.0.0.1: icmp_seq=3 ttl=64 time=3.46 ms

Above I configured ping to send a packet every 3 seconds. This caused the timestamp to be 3 on each output after the first since each timestamp was 3 seconds apart. Remember, the -i option shows the time since the last timestamp.

Relative Timestamps for Linux Output

The -r option converts existing timestamps into relative times like "26m32s ago". Again, I have a coworker who had a few clever uses for this in his shell scripts (Maybe he will share?). To demonstrate this I will use the journalctl command to display system logs. We will then pipe it to the ts command to convert them to relative timestamps.

NOTE: Both "Time::Duration" and "Date::Parse" perl modules need to be installed for this option to work. You can read "Installing Perl Modules with cpan" if you need help.

Here we print the last 4 lines of our system log with journalctl.

[root@putor log]# journalctl -f -n 4
-- Logs begin at Wed 2020-04-01 13:23:42 EDT. --
Feb 15 14:48:05 putor sudo[132384]: pam_unix(sudo:session): session closed for user root
Feb 15 14:49:14 putor savona[132410]: test
Feb 15 14:49:30 putor savona[132422]: This is a log entry
Feb 15 14:50:48 putor savona[132444]: I will add one more for good measure

Here we print the same 4 lines, this time piping it to ts -r to convert the timestamps to relative times.

[root@putor log]# journalctl -f -n 4 | ts -r
-- Logs begin at Wed 2020-04-01 13:23:42 EDT. --
9m4s ago putor sudo[132384]: pam_unix(sudo:session): session closed for user root
7m55s ago putor savona[132410]: test
7m39s ago putor savona[132422]: This is a log entry
6m21s ago putor savona[132444]: I will add one more for good measure

NOTE: You can also covert timestamps into any format you desire, continue reading for instructions.

Formatting Timestamps with the ts Command

With the ts command, formatting timestamps is very similar to the formatting used in the date command. Let's take a look at some examples.

[savona@putor ~]$ echo " - %B Shows me just the month by name" | ts %B
February  - %B Shows me just the month by name

[savona@putor ~]$ echo " - %s Shows me the UNIX epoch" | ts %s
1613420169  - %s Shows me the UNIX epoch

Of course you can combine these formatting strings to make any format you desire. Here are some more complex examples.

[savona@putor ~]$ echo " - %l\":\"%M%p Shows me 12 hour clock" | ts %l":"%M%p
 3:23PM  - %l":"%M%p Shows me the normal 12 hour time

[savona@putor ~]$ echo " - %%m-%d-%Y Shows me the month-day-year" | ts %m-%d-%Y
02-15-2021  - %%m-%d-%Y Shows me the month-day-year

[savona@putor ~]$ echo " - %B\" \"%d,%y Shows me the month day, year as usually written in English" | ts %B" "%d,%Y
February 15,2021  - %B" "%d,%y Shows me the month day, year as usually written in English

You can also format existing timestamps by combining the -r option with any formatting parameters. Let's look at an example.

Here is a normal system log entry, take note of the timestamp.

Feb 15 15:32:26 putor sudo[134299]: pam_unix(sudo:session): session opened for user root(uid=0) by (uid=1000)

The journalctl timestamps are already pretty friendly. However, we can change them to whatever we desire. In this example we convert them to something very natural to Americans using %B" "%d,%Y-%l":"%M%p.

[savona@putor ~]$ sudo journalctl -f | ts -r %B" "%d,%Y-%l":"%M%p
February 15,2021- 3:32PM putor sudo[134277]: pam_unix(sudo:session): session opened for user root(uid=0) by (uid=1000)

For all formatting parameters see strftime.