10

I am using the 'tee' command in order to capture the results of a long bash command to a file.

Can the file I emit with tee somehow prefix each line with the timestamp of when the line was written? I'm looking for a solution in which each line would have a different date time value... not the same value prefixed on each line.

The reason I want this is that it would be very useful to know when each line was emitted later when I read through the file to understand where the slow areas were.

2 Answers2

8

If tee can't do something, pipe it to a program which does. moreutils has a tool named ts whose purpose is exactly this:

$ echo test | ts
Feb 02 13:17:27 test

If you want to timestamp everything, the usage should be obvious:

myapp | ts | tee app.log

Other combinations are possible; for example, to timestamp only screen output or only the logfile:

myapp | tee app.log | ts
myapp | tee >(ts > app.log)
myapp | tee /dev/tty | ts > app.log
myapp | pee "ts > app.log" "cat"
myapp | pee "cat > app.log" "ts"

(Yes, that last one is also from moreutils.)

grawity
  • 501,077
2

An alternative to ts:

echo "foo" | stdbuf -o0 sed 's/%/%%/g' | xargs -d '\n' -I {} date '+%F %T {}' | tee -a "/tmp/foo.log"

Output:

# cat "/tmp/foo.log"
2022-02-24 09:43:00 foo

Example to log stdout and stderr to a file (remove /dev/null to write to terminal, too):

exec &> >(stdbuf -o0 sed 's/%/%%/g' | xargs -d '\n' -I {} date '+%F %T {}' | tee -a "/tmp/std.log" >/dev/null )

Another alternative by using awk:

echo "foo" | xargs -d'\n' -I{} echo '{}' | awk '{ print strftime("%F %T"), $0; fflush(); }' | tee -a "/tmp/foo.log"
mgutt
  • 1,198
  • 2
  • 17
  • 35