0

I have the following bash command to tee script output to stdout and logfile. It works and I can see the live output. However the date is not changing. Is there any way to instruct exec to evaluate date in a dynamic way.

#!/bin/bash

LOGFILE="/tmp/te/script.log"
exec 1> >( stdbuf -e 0 -o 0 sed "s/^/$(date '+[%F %T]'): /" | tee -a ${LOGFILE}) 2>&1

echo "Started"
sleep 2
echo "Done sleeping"
sleep 2
echo "Another sleep"
sleep 2

echo "Done"

Thanks

Anandan
  • 319
  • 3
  • 10
  • Completely to be expected. `sed` is started *once*, and `date` is run *once* -- you wouldn't want it to be any other way; invoking external tools is extremely slow, so the log process couldn't necessarily keep up if you had a fast run of content going through. – Charles Duffy Sep 26 '17 at 16:07

2 Answers2

4

You might want to use ts to add timestamps instead. For Ubuntu, apt install moreutils

exec 1> >(stdbuf -e0 -o0 ts '[%F %T]' | tee -a "$LOGFILE") 2>&1
# ...................... ^^^^^^^^^^^^
glenn jackman
  • 238,783
  • 38
  • 220
  • 352
0

If you have bash 4.1 or newer, it has a very efficient means of calculating timestamp via printf %()T. Thus:

logfile="/tmp/te/script.log"
exec > >(while IFS= read -r line; do
          printf '%([%F %T])T %s\n' -1 "$line"
         done >>"$logfile") 2>&1

This uses a BashFAQ #1 while read loop to iterate over lines, and uses printf to generate a line of output with the current timestamp for each.

(If you get the error printf: `(': invalid format character, that means your bash is too old; you could instead printf '%s %s\n' "$(date '+[%F %T]')" "$line", but this is going to be much slower).

Charles Duffy
  • 280,126
  • 43
  • 390
  • 441