Programing

타임 스탬프를 stdin 앞에 추가하는 Unix 유틸리티가 있습니까?

crosscheck 2020. 5. 29. 07:58
반응형

타임 스탬프를 stdin 앞에 추가하는 Unix 유틸리티가 있습니까?


파이썬에서 이것에 대한 간단한 작은 스크립트를 작성하게되었지만, 텍스트에 각 줄 앞에 텍스트를 넣을 수있는 유틸리티가 있는지 궁금합니다. 내 경우에는 타임 스탬프입니다. 이상적으로는 다음과 같이 사용됩니다.

cat somefile.txt | prepend-timestamp

(sed에 대답하기 전에 다음을 시도했습니다.

cat somefile.txt | sed "s/^/`date`/"

그러나 sed가 실행될 때 date 명령을 한 번만 평가하므로 각 타임 라인에 동일한 타임 스탬프가 잘못 추가됩니다.)


시도해 볼 수 있습니다 awk:

<command> | awk '{ print strftime("%Y-%m-%d %H:%M:%S"), $0; fflush(); }'

<command>라인 버퍼 출력 생성 해야합니다 . 즉, 각 라인 후에 출력 스트림을 플러시합니다. 타임 스탬프 awk추가는 라인의 끝이 입력 파이프에 나타난 시간입니다.

awk에 오류가 표시되면 gawk대신 시도하십시오 .


ts에서 moreutils은 입력의 모든 라인에 타임 스탬프를 앞에 추가합니다 당신은 그것을 제공합니다. strftime을 사용하여 형식을 지정할 수도 있습니다.

$ echo 'foo bar baz' | ts
Mar 21 18:07:28 foo bar baz
$ echo 'blah blah blah' | ts '%F %T'
2012-03-21 18:07:30 blah blah blah
$ 

설치하려면 :

sudo apt-get install moreutils

annotate , 해당 링크를 통해 또는 annotate-output데비안 devscripts패키지 에서 사용 가능 합니다.

$ echo -e "a\nb\nc" > lines
$ annotate-output cat lines
17:00:47 I: Started cat lines
17:00:47 O: a
17:00:47 O: b
17:00:47 O: c
17:00:47 I: Finished with exitcode 0

주어진 답변을 가장 간단한 답변으로 증류 :

unbuffer $COMMAND | ts

Ubuntu에서는 expect-dev 및 moreutils 패키지에서 제공됩니다.

sudo apt-get install expect-dev moreutils

이건 어때요?

cat somefile.txt | perl -pne 'print scalar(localtime()), " ";'

라이브 타임 스탬프를 얻으려는 욕구로 판단하면 로그 파일이나 다른 것을 실시간으로 업데이트하고 싶습니까? 아마도

tail -f /path/to/log | perl -pne 'print scalar(localtime()), " ";' > /path/to/log-with-timestamps

데몬 툴 에는 tai64ntai64nlocal 이라는 유틸리티 쌍이 있는데, 타임 스탬프를 추가하여 메시지를 기록하기 위해 만들어졌습니다.

예:

cat file | tai64n | tai64nlocal

Kieron의 답변은 지금까지 가장 좋은 답변입니다. 첫 번째 프로그램이 버퍼링하기 때문에 문제가 발생하면 unbuffer 프로그램을 사용할 수 있습니다.

unbuffer <command> | awk '{ print strftime("%Y-%m-%d %H:%M:%S"), $0; }'

대부분의 리눅스 시스템에 기본적으로 설치됩니다. 직접 빌드해야하는 경우 예상 패키지의 일부입니다.

http://expect.nist.gov


read (1) 명령을 사용하여 표준 입력에서 한 번에 한 줄씩 읽은 다음 date 앞에 추가 된 행을 date (1)을 사용하여 선택한 형식으로 출력하십시오.

$ cat timestamp
#!/bin/sh
while read line
do
  echo `date` $line
done
$ cat somefile.txt | ./timestamp

나는 유닉스 사람이 아니지만 사용할 수 있다고 생각합니다.

gawk '{print strftime("%d/%m/%y",systime()) $0 }' < somefile.txt

#! /bin/sh
unbuffer "$@" | perl -e '
use Time::HiRes (gettimeofday);
while(<>) {
        ($s,$ms) = gettimeofday();
        print $s . "." . $ms . " " . $_;
}'

Here's my awk solution (from a Windows/XP system with MKS Tools installed in the C:\bin directory). It is designed to add the current date and time in the form mm/dd hh:mm to the beginning of each line having fetched that timestamp from the system as each line is read. You could, of course, use the BEGIN pattern to fetch the timestamp once and add that timestamp to each record (all the same). I did this to tag a log file that was being generated to stdout with the timestamp at the time the log message was generated.

/"pattern"/ "C\:\\\\bin\\\\date '+%m/%d %R'" | getline timestamp;
print timestamp, $0;

where "pattern" is a string or regex (without the quotes) to be matched in the input line, and is optional if you wish to match all input lines.

This should work on Linux/UNIX systems as well, just get rid of the C\:\\bin\\ leaving the line

             "date '+%m/%d %R'" | getline timestamp;

This, of course, assumes that the command "date" gets you to the standard Linux/UNIX date display/set command without specific path information (that is, your environment PATH variable is correctly configured).


Mixing some answers above from natevw and Frank Ch. Eigler.

It has milliseconds, performs better than calling a external date command each time and perl can be found in most of the servers.

tail -f log | perl -pne '
  use Time::HiRes (gettimeofday);
  use POSIX qw(strftime);
  ($s,$ms) = gettimeofday();
  print strftime "%Y-%m-%dT%H:%M:%S+$ms ", gmtime($s);
  '

Alternative version with flush and read in a loop:

tail -f log | perl -pne '
  use Time::HiRes (gettimeofday); use POSIX qw(strftime);
  $|=1;
  while(<>) {
    ($s,$ms) = gettimeofday();
    print strftime "%Y-%m-%dT%H:%M:%S+$ms $_", gmtime($s);
  }'

$ cat somefile.txt | sed "s/^/`date`/"

you can do this (with gnu/sed):

$ some-command | sed "x;s/.*/date +%T/e;G;s/\n/ /g"

example:

$ { echo 'line1'; sleep 2; echo 'line2'; } | sed "x;s/.*/date +%T/e;G;s/\n/ /g"
20:24:22 line1
20:24:24 line2

of course, you can use other options of the program date. just replace date +%T with what you need.


caerwyn's answer can be run as a subroutine, which would prevent the new processes per line:

timestamp(){
   while read line
      do
         echo `date` $line
      done
}

echo testing 123 |timestamp

Disclaimer: the solution I am proposing is not a Unix built-in utility.

I faced a similar problem a few days ago. I did not like the syntax and limitations of the solutions above, so I quickly put together a program in Go to do the job for me.

You can check the tool here: preftime

There are prebuilt executables for Linux, MacOS, and Windows in the Releases section of the GitHub project.

The tool handles incomplete output lines and has (from my point of view) a more compact syntax.

<command> | preftime

It's not ideal, but I though I'd share it in case it helps someone.


doing it with date and tr and xargs on OSX:

alias predate="xargs -I{} sh -c 'date +\"%Y-%m-%d %H:%M:%S\" | tr \"\n\" \" \"; echo \"{}\"'"
<command> | predate

if you want milliseconds:

alias predate="xargs -I{} sh -c 'date +\"%Y-%m-%d %H:%M:%S.%3N\" | tr \"\n\" \" \"; echo \"{}\"'"

but note that on OSX, date doesn't give you the %N option, so you'll need to install gdate (brew install coreutils) and so finally arrive at this:

alias predate="xargs -I{} sh -c 'gdate +\"%Y-%m-%d %H:%M:%S.%3N\" | tr \"\n\" \" \"; echo \"{}\"'"

If the value you are prepending is the same on every line, fire up emacs with the file, then:

Ctrl + <space>

at the beginning of the of the file (to mark that spot), then scroll down to the beginning of the last line (Alt + > will go to the end of file... which probably will involve the Shift key too, then Ctrl + a to go to the beginning of that line) and:

Ctrl + x r t

Which is the command to insert at the rectangle you just specified (a rectangle of 0 width).

2008-8-21 6:45PM <enter>

Or whatever you want to prepend... then you will see that text prepended to every line within the 0 width rectangle.

UPDATE: I just realized you don't want the SAME date, so this won't work... though you may be able to do this in emacs with a slightly more complicated custom macro, but still, this kind of rectangle editing is pretty nice to know about...

참고URL : https://stackoverflow.com/questions/21564/is-there-a-unix-utility-to-prepend-timestamps-to-stdin

반응형