如何添加时间戳STDERR重定向(How to add timestamp to STDERR re

2019-07-20 12:35发布

在bash / ksh的可我们添加时间戳STDERR重定向?

例如myscript.sh 2> error.log中

我想写在日志太时间戳。

Answer 1:

如果你在谈论的最多最新时间戳在每一行,这东西你可能会想在您的实际脚本做(但请参阅下面的一个极好的解决方案,如果你没有力量去改变它)。 如果你只是想在自己的行标记日期脚本开始写之前,我会使用:

( date 1>&2 ; myscript.sh ) 2>error.log

你需要的是通过其他程序,可以添加时间戳到每行一招,管标准错误。 你可以这样做一个C程序,但有只使用一种更为狡猾的方式bash

首先,创建一个脚本,将时间戳添加到每个行(称为predate.sh ):

#!/bin/bash
while read line ; do
    echo "$(date): ${line}"
done

例如:

( echo a ; sleep 5 ; echo b ; sleep 2 ; echo c ) | ./predate.sh

生产:

Fri Oct  2 12:31:39 WAST 2009: a
Fri Oct  2 12:31:44 WAST 2009: b
Fri Oct  2 12:31:46 WAST 2009: c

然后,你需要另外的技巧,可以交换输出和错误,在这里这个小怪物:

( myscript.sh 3>&1 1>&2- 2>&3- )

然后,它通过简单的时戳的两个技巧结合stdout ,并将其重定向到文件:

( myscript.sh 3>&1 1>&2- 2>&3- ) | ./predate.sh >error.log

下面的记录表明这个动作:

pax> cat predate.sh
    #!/bin/bash
    while read line ; do
        echo "$(date): ${line}"
    done
pax> cat tstdate.sh
    #!/bin/bash
    echo a to stderr then wait five seconds 1>&2
    sleep 5
    echo b to stderr then wait two seconds 1>&2
    sleep 2
    echo c to stderr 1>&2
    echo d to stdout
pax> ( ( ./tstdate.sh ) 3>&1 1>&2- 2>&3- ) | ./predate.sh >error.log
    d to stdout
pax> cat error.log
    Fri Oct  2 12:49:40 WAST 2009: a to stderr then wait five seconds
    Fri Oct  2 12:49:45 WAST 2009: b to stderr then wait two seconds
    Fri Oct  2 12:49:47 WAST 2009: c to stderr

如已经提到的, predate.sh将前缀的每个线带时间戳和tstdate.sh是一个简单的测试程序写入到stdoutstderr与特定的时间间隙。

当您运行命令,你实际上得到"d to stdout"写入stderr(但是这是您的TTY设备或任何其他stdout可以一直当你开始)。 时间戳的stderr行写入你想要的文件。



Answer 2:

devscripts包在于Debian / Ubuntu包含脚本称为annotate-output其中这是否(对于stdout和stderr)。

$ annotate-output make
21:41:21 I: Started make
21:41:21 O: gcc -Wall program.c
21:43:18 E: program.c: Couldn't compile, and took me ages to find out
21:43:19 E: collect2: ld returned 1 exit status
21:43:19 E: make: *** [all] Error 1
21:43:19 I: Finished with exitcode 2


Answer 3:

下面是一个使用一个版本while read循环PAX一样 ,但不要求额外的文件描述符或者一个单独的脚本(虽然你可以使用一个)。 它使用进程替换:

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

使用PAX的 predate.sh

myscript.sh 2> >( predate.sh > error.log )


Answer 4:

节目ts从moreutils包管标准输入到标准输出,和前缀与时间戳的每一行。

前缀标准输出线: command | ts command | ts
前缀两者输出和错误: command 2>&1 | ts command 2>&1 | ts



Answer 5:

我喜欢那些移植的shell脚本,但有点不安,他们叉/ EXEC日期(1)每行。 这里是一个快速的Perl一行程序更有效地做同样的:

perl -p -MPOSIX -e 'BEGIN {$!=1} $_ = strftime("%T ", localtime) . $_'

要使用它,只是通过它的饲料标准输入此命令输入:

(echo hi; sleep 1; echo lo) | perl -p -MPOSIX -e 'BEGIN {$|=1} $_ = strftime("%T ", localtime) . $_'


Answer 6:

而不是写一个脚本来管,我喜欢写日志记录器的脚本中的函数,然后发送过程的整体并入其与支架,像这样:

 # 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


Answer 7:

如果你想回重定向到stdout,我发现你必须这样做:

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

不知道为什么我需要>在前面( ,所以<(但那是什么工作。



Answer 8:

我对所有的现有解决方案太懒惰...所以我想通了新的(用于工程stdout可用于调整stderr以及):

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

将保存到文件和打印这样的事情: 11/3/16 16:07:52 output

细节:

-L1装置“为每个新行”

-I{}是指“取代{}由输入”

bash -c用于更新$(date)为新的呼叫,每次

%x %T格式时间戳的最小形式。

它应该工作就像一个魅力,如果stdoutstderr没有引号(”或'),如果有(或者可能有),这是更好地使用:

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

(从我的回答参加了另一个话题: https://stackoverflow.com/a/41138870/868947 )



Answer 9:

#!/bin/bash

DEBUG=1

LOG=$HOME/script_${0##*/}_$(date +%Y.%m.%d-%H.%M.%S-%N).log
ERROR=$HOME/error.log

exec 2> $ERROR
exec 1> >(tee -ai $LOG)

if [ $DEBUG = 0 ] ; then
    exec 4> >(xargs -i echo -e "[ debug ] {}")
else
    exec 4> /dev/null
fi

# test
echo " debug sth " >&4
echo " log sth normal "
type -f this_is_error
echo " errot sth ..." >&2
echo " finish ..." >&2>&4
# close descriptor 4
exec 4>&-


Answer 10:

这件事情:nohup的myscript.sh 2>>(当读取线;请回声 “$(日期):$ {线}”;完成> mystd.err)<的/ dev / null的&

作品本身,而是当我注销并重新登录到服务器,这是行不通的。 这是mystd.err停止与标准错误流得到填充,即使我的过程(在这里myscript.sh)仍然运行。

是否有人知道如何找回在mystd.err文件找回了走失的标准错误?



Answer 11:

我以为我想补充我的2美分的价值..

#!/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}`
空间出了名的,所以它看起来不错,其中15是发出最大的空间,增加如果需要的话

输出>>日期 - 进程名称 - 进程ID - INFO - 消息

Jun 27 13:57:20 - process name     - 18866 - INFO - hi


Answer 12:

如何时间戳剩余的输出,都重定向到标准输出?

这个答案结合从上面,以及从UNIX stackexchange一些技术, 在这里和这里 。 bash > = 4.2假设,但其他先进的炮弹可能工作。 对于< 4.2 ,取代printf与(慢)呼叫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

要恢复标准输出/标准错误:

exec 1>&6 2>&7

然后,您可以用tee来的时间戳发送到stdout 一个日志文件。

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

不是一个坏主意,有清理代码如果进程退出而不会出现错误:

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}"
}


Answer 13:

重定向采取秩序。 试试这个:

给定一个脚本 -

$: cat tst
echo a
sleep 2
echo 1 >&2
echo b
sleep 2
echo 2 >&2
echo c
sleep 2
echo 3 >&2
echo d

我得到以下

$: ./tst 2>&1 1>stdout | sed 's/^/echo $(date +%Y%m%dT%H%M%S) /; e'
20180925T084008 1
20180925T084010 2
20180925T084012 3

并不亚于我不喜欢的awk,它避免了重复子调用日期。

$: ./tst 2>&1 1>stdout | awk "{ print strftime(\"%Y%m%dT%H%M%S \") \$0; fflush() }"; >stderr

$: cat stderr
20180925T084414 1
20180925T084416 2
20180925T084418 3

$: cat stdout
a
b
c
d


文章来源: How to add timestamp to STDERR redirection