How to add timestamp to STDERR redirection

后端 未结 13 2329
感情败类
感情败类 2020-11-28 05:10

In bash/ksh can we add timestamp to STDERR redirection?

E.g. myscript.sh 2> error.log

I want to get a timestamp written on the log too.

相关标签:
13条回答
  • 2020-11-28 05:31

    Rather than writing a script to pipe to, I prefer to write the logger as a function inside the script, and then send the entirety of the process into it with brackets, like so:

     # Vars    
     logfile=/path/to/scriptoutput.log
    
     # Defined functions
     teelogger(){
       log=$1
       while read line ; do
         print "$(date +"%x %T") :: $line" | tee -a $log
       done
     }
    
    
    # Start process
    {
    
    echo 'well'
    sleep 3
    echo 'hi'
    sleep 3
    echo 'there'
    sleep 3
    echo 'sailor'
    
    }  |  teelogger $logfile
    
    0 讨论(0)
  • 2020-11-28 05:34

    I was too lazy for all current solutions... So I figured out new one (works for stdout could be adjusted for stderr as well):

    echo "output" | xargs -L1 -I{} bash -c "echo \$(date +'%x %T') '{}'" | tee error.log
    

    would save to file and print something like that: 11/3/16 16:07:52 output

    Details:

    -L1 means "for each new line"

    -I{} means "replace {} by input"

    bash -c is used to update $(date) each time for new call

    %x %T formats timestamp to minimal form.

    It should work like a charm if stdout and stderr doesn't have quotes (" or `). If it has (or could have) it's better to use:

    echo "output" | awk '{cmd="(date +'%H:%M:%S')"; cmd | getline d; print d,$0; close(cmd)} | tee error.log'
    

    (Took from my answer in another topic: https://stackoverflow.com/a/41138870/868947)

    0 讨论(0)
  • 2020-11-28 05:36

    The program ts from the moreutils package pipes standard input to standard output, and prefixes each line with a timestamp.

    To prefix stdout lines: command | ts
    To prefix both stdout and stderr: command 2>&1 | ts

    0 讨论(0)
  • 2020-11-28 05:36

    Thought I would add my 2 cents worth..

    #!/bin/sh
    
    timestamp(){
      name=$(printf "$1%*s" `expr 15 - ${#1}`)
      awk "{ print strftime(\"%b %d %H:%M:%S\"), \"- $name -\", $$, \"- INFO -\", \$0; fflush() }";
    }
    
    echo "hi" | timestamp "process name" >> /tmp/proccess.log
    

    printf "$1%*s" `expr 15 - ${#1}`
    Spaces the name out so it looks nice, where 15 is the max space issued, increase if desired

    outputs >> Date - Process name - Process ID - INFO - Message

    Jun 27 13:57:20 - process name     - 18866 - INFO - hi
    
    0 讨论(0)
  • 2020-11-28 05:45

    Here's a version that uses a while read loop like pax's, but doesn't require extra file descriptors or a separate script (although you could use one). It uses process substitution:

    myscript.sh 2> >( while read line; do echo "$(date): ${line}"; done > error.log )
    

    Using pax's predate.sh:

    myscript.sh 2> >( predate.sh > error.log )
    
    0 讨论(0)
  • 2020-11-28 05:47

    How about timestamping the remaining output, redirecting all to stdout?

    This answer combines some techniques from above, as well as from unix stackexchange here and here. bash >= 4.2 is assumed, but other advanced shells may work. For < 4.2, replace printf with a (slower) call to date.

    : ${TIMESTAMP_FORMAT:="%F %T"} # override via environment
    _loglines() { 
        while IFS= read -r _line ; do 
          printf "%(${TIMESTAMP_FORMAT})T#%s\n" '-1' "$_line";
        done;
    }
    exec 7<&2 6<&1
    exec &> >( _loglines )
    # Logit
    

    To restore stdout/stderr:

    exec 1>&6 2>&7
    

    You can then use tee to send the timestamps to stdout and a logfile.

    _tmpfile=$(mktemp)
    exec &> >( _loglines | tee $_tmpfile )
    

    Not a bad idea to have cleanup code if the process exited without error:

    trap "_cleanup \$?" 0 SIGHUP SIGINT SIGABRT SIGBUS SIGQUIT SIGTRAP SIGUSR1 SIGUSR2 SIGTERM
    _cleanup() { 
        exec >&6 2>&7
        [[ "$1" != 0 ]] && cat "$_logtemp"
        rm -f "$_logtemp"
        exit "${1:-0}"
    }
    
    0 讨论(0)
提交回复
热议问题