3

I'm looking to capture the output of a shell script execution in real time to enrich it with information giving the date and time.

To illustrate, I have for example a script of this type that I must not modify:

#!/bin/bash
for i in 2 3 1
do
  echo "Waiting for $i seconds ..."
  sleep $i
done

The script produces the following output:

Waiting for 2 seconds ...
Waiting for 3 seconds ...
Waiting for 1 seconds ...

I am trying to produce the output of the type:

2021-06-16 11:44:48 [INFO] Waiting for 2 seconds ...
2021-06-16 11:44:50 [INFO] Waiting for 3 seconds ...
2021-06-16 11:44:53 [INFO] Waiting for 1 seconds ...

I use the following shell functions for formatting in a script that runs my initial script:

function log {
   echo `date +%Y-%m-%d" "%H:%M:%S`" $@"
   if [ "$LOGFILE" != "" ]
   then
      echo `date +%Y-%m-%d" "%H:%M:%S`" $@" >>$LOGFILE
   fi
}

function loginf { log "[INFO] $@" }

I manage very well with a while loop on a read to capture the output of my script, but I get all the lines at the same time (end of its execution) and therefore all lines have the same datetime. I try to get the lines each time the script produces a line and not at the end of the execution.

pLumo
  • 28,011
  • 2
  • 65
  • 97
  • How do you call your initital script? This works well for me : ./script1.sh | while IFS= read -r l; do loginf "$l"; done. See also https://serverfault.com/questions/72744/command-to-prepend-string-to-each-line – pLumo Jun 16 '21 at 13:41
  • 1
    ./script.sh | ts "%Y-%m-%d %H:%M:%S [INFO]" –  Jun 16 '21 at 13:57
  • I created a script that contains your two functions and then the following code: while { read; } do loginf $REPLY; done. Running ./script1 | ./script2 (where script1 is your first script and script2 the above mentioned script) gives correct output for me, ie. different timestamps. – raj Jun 16 '21 at 13:58
  • don't need to use echo really, could just do f(){ date "+%Y-%m-%d %H:%M:%S [INFO] $*"; }; f one two three –  Jun 16 '21 at 14:08
  • f(){ printf '%(%Y-%m-%d %H:%M:%S)T [%s] %s\n' -1 INFO "$*"; }; f one two three even better... –  Jun 16 '21 at 14:10

2 Answers2

2

The ts command from package moreutils does precisely what you are looking for:

./script.sh | ts

It has various options for formatting the time stamp. For instance,

ts '%F %T [INFO]'

will give you the exact format you use in your question.

zwets
  • 12,790
0

You can either use ts:

./your_script.sh | ts

Of, if you need something portable that works on systems where ts is not installed, you can do that in a simple while loop using the built-in read command:

./your_script.sh | while read line; do echo "$(date +'%Y-%m-%d %H:%M:%S') [INFO] $line"; done
vog
  • 127