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


168

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

cat somefile.txt | prepend-timestamp

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

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

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


cat somefile.txt"오해의 소지가"조금? "한 번에"발생할 것으로 예상되며 단일 타임 스탬프가 있습니다. 이것이 더 좋은 테스트 프로그램이 (echo a; sleep 1; echo b; sleep 3; echo c; sleep 2)아닐까요?
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

답변:


185

사용할 수 있습니다 awk:

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

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

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


31
내 시스템에서 'awk'자체가 버퍼링되었습니다. 로그 파일에는 문제가 될 수 있습니다. awk '{print strftime ( "% Y- % m- % dT % H : % M : % S"), $ 0; fflush (); } '
user47741

19
strftime ()은 GNU awk 확장명 인 것처럼 보이므로 Mac OS를 사용하는 경우 awk 대신 gawk를 사용하십시오.
Joe Shaw

bash가 얼마나 강력한 지 놀라게하지 않습니다. 이 복잡한 작업에 대한 쉬운 해결책이 없을 것이라고 생각했습니다.
recluze

2
OS X 사용자의 경우 gawk대신 대신 설치 하여 사용해야합니다 awk. MacPorts가있는 경우 :sudo port install gawk
Matt Williamson

5
@teh_senaus으로는 지금까지 내가 아는 한, awkstrftime()밀리 초 정밀도를 가지고 있지 않습니다. 그러나 date명령을 사용할 수 있습니다 . 기본적으로 나노초를 3 자로 자릅니다. 다음과 같이 보일 것입니다 : COMMAND | while read -r line; do echo "$(date '+%Y-%m-%d %T.%3N') $line"; done. % T와 함께 % H : % M : % S를 축약 할 수 있습니다. awk어떤 이유로 든 계속 사용 하려면 다음을 수행하십시오.COMMAND | awk '{ "date +%Y-%m-%d\\ %T.%3N" | getline timestamp; print timestamp, $0; fflush(); }'
Six

190

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

2
stderr을 동시에 캡처하고 스탬프하는 방법 : bad command 2>&1 | ts결과 :Jan 29 19:58:31 -bash: bad: command not found
rymo

시간 형식을 사용하고 싶습니다 2014 Mar 21 18:07:28. 어떻게 구할 수 있습니까?
becko dec

@becko 일 -에 따라 매뉴얼 페이지 하는 줄 strftime인수로 형식 문자열을 : [.. command ..] | ts '%Y %b %d %T'예를 들어.
Toby Speight

2
OS X의 경우 brew install moreutils. UTC를 출력하려면 TZ를 로컬로 설정할 수 있습니다 (예 :ls -l |TZ=UTC ts '%Y-%m-%dT%H:%M:%SZ'
karmakaze

1
@Dorian 이것은 루비가 출력을 버퍼링하기 때문입니다. 수면 전에 버퍼를 ruby -e "puts 1; STDOUT.flush; sleep 1; puts 2; STDOUT.flush; sleep 2; puts 3" | ts '%F %T'
비우면

45

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

1
이것은 훌륭한 솔루션이지만 파이프 출력 또는 서브 쉘 출력에서는 작동하지 않습니다. 인수로 제공 한 프로그램 또는 스크립트의 출력 만 다시 형식화합니다.
slm

1
주석 출력은 훌륭하게 작동하고 사용하기 쉽지만 실제로는 느립니다.
Paul Brannan

31

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

unbuffer $COMMAND | ts

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

sudo apt-get install expect-dev moreutils

1
그건 expect아니, expect-dev하지만 전에서 후반 당긴이 작품 때문에. (우분투 14.10, 바이너리가 어떤 시점에서 다른 패키지로 옮겨 졌는지 궁금합니다.)
Marius Gedminas

우분투 14.04 LTS의 경우, 여전히 있습니다expect-dev
Willem

2
당신은 밀리 초 정확성, 사용과 경과 시간을 얻을하려는 경우 unbuffer $COMMAND | ts -s %.s( -s경과 시간과 경우 %.s소수 부분에 초 단위 시간)
그렉 Witczak

24

이건 어때요?

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

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

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

4
이 perl 예제는 우분투 배포에서 사용자로 일할 때 특히 유용했습니다. 우분투 배포에서는 분명히 'gawk'대신 'mawk'를 사용합니다. 감사!
opello

4
+1은 기본 우분투 설치에서 편리합니다. 나는 tail -f /path/to/log | perl -pne 'use POSIX qw(strftime); print strftime "%Y-%m-%dT%H:%M:%SZ ", gmtime();'더 간단한 버전이 생성하는 wacko 대신 ISO8601 / RFC3339 스타일 날짜를 얻었습니다.
natevw

1
도착한 타임 스탬프 된 로그 출력을보고 싶다면 BEGIN { $|++; }Perl이 각 라인으로 출력을 플러시하도록 print 문 앞에 추가하는 것이 도움이 될 수 있습니다 .

2
perl 스크립트를 더 짧게 줄일 수 있습니다 ls | perl -pne 'print localtime." "'. 스칼라 변환은 문자열 연결로 인해 발생합니다.
rahul

왜 옵션 -p-n옵션을 모두 사용 합니까? -n지정한 경우 중복 된 것 같습니다 -p.
Davor Cubranic


18

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

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

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

http://expect.nist.gov


'언 버퍼'는 때때로 호출 된 프로그램의 리턴 결과를 숨기므로 Jenkins 또는 리턴 상태에 의존하는 다른 것에는 유용하지 않습니다.
oskarpearson

10

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

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

2
라인 당 새로운 프로세스를 분기하므로 약간 헤비급이지만 작동합니다!
Joe Shaw

3

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

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

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

2

다음은 awk 솔루션입니다 (C : \ bin 디렉토리에 MKS Tools가 설치된 Windows / XP 시스템). 각 줄을 읽을 때 시스템에서 해당 타임 스탬프를 가져온 각 줄의 시작 부분에 mm / dd hh : mm 형식으로 현재 날짜와 시간을 추가하도록 설계되었습니다. 물론 BEGIN 패턴을 사용하여 타임 스탬프를 한 번 페치하고 해당 타임 스탬프를 각 레코드에 추가 할 수 있습니다 (모두 동일). 로그 메시지가 생성 될 때 타임 스탬프로 stdout에 생성 된 로그 파일에 태그를 지정하기 위해이 작업을 수행했습니다.

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

여기서 "pattern"은 입력 줄에서 일치시킬 문자열 또는 따옴표 (따옴표 제외)이며 모든 입력 줄을 일치 시키려면 선택 사항입니다.

이것은 Linux / UNIX 시스템에서도 작동합니다. C \ : \\ bin \\을 제거하십시오.

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

물론 이것은 "date"명령이 특정 경로 정보가없는 표준 Linux / UNIX 날짜 표시 / 설정 명령 (즉, 환경 PATH 변수가 올바르게 구성되어 있음)으로 이동한다고 가정합니다.


OS XI에서 date 명령 앞에 공백이 필요했습니다. 슬프게도 각 줄의 명령을 다시 평가하지 않는 것 같습니다. 다른 사람들이 제안했듯이, tail -f에 타임 스탬프를 추가하려고합니다.
마크 베넷

2

natevw 와 Frank Ch의 위의 답변을 혼합하십시오 . 아이 글러

밀리 초가 있으며 date매번 외부 명령을 호출하는 것보다 성능이 뛰어나며 대부분의 서버에서 perl을 찾을 수 있습니다.

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);
  '

루프에서 플러시 및 읽기가 가능한 대체 버전 :

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);
  }'

1
위의 두 가지 결함 : 1. $ ms가 정렬되지 않고 채워지지 않습니다. 2. 로그의 % 코드가 엉망이됩니다. 따라서 인쇄 라인 대신 다음을 사용했습니다. printf "%s+%06d %s", (strftime "%Y-%m-%dT%H:%M:%S", gmtime($s)), $ms, $_;
Simon Pickup

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

이 작업을 수행 할 수 있습니다 ( gnu / sed 사용 ).

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

예:

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

물론, 당신은 프로그램 날짜 의 다른 옵션을 사용할 수 있습니다 . date +%T필요한 것으로 교체하십시오 .


1

caerwyn의 답변은 서브 루틴으로 실행될 수 있으므로 라인 당 새로운 프로세스를 방지 할 수 있습니다.

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

echo testing 123 |timestamp

3
어떻게하면 date모든 라인에 스폰 되지 않습니까?
Gyom

@Gyom 모든 라인에서 날짜가 생성되는 것을 막지는 않습니다. 이 모든 라인을 생성 하는 것을 방지 합니다. 나는 bash에서 다음과 같이 덧붙인다 timestamp() { while read line; do echo "$(date) $line"; done; }; export -f timestamp.
smbear

서브 프로세스로 호출 날짜는 여전히 모든 라인에 대해 생성되는 것을 의미하지만 처음부터 스크립트를 실행합니다.
피터 한센

3
date모든 줄에 대해 산란 명령을 방지하려면 % (datespec) T 형식으로 bash printf내장을 사용하십시오 . 따라서 다음과 같이 보일 수 있습니다. 쉘 내장은 생성되지 않습니다. Datespec 형식은 같다 즉 형식을 지원합니다. 이 지정자를 지원하는 버전이 확실하지 않으므로 bash가 필요 합니다. timestamp() { while IFS= read -r line; do printf "%(%F %T)T %s\n" -1 "$line"; done; }strftime(3)dateprintf
Mindaugas Kubilius

1

면책 조항 : 내가 제안하는 솔루션은 Unix 내장 유틸리티가 아닙니다.

며칠 전에 비슷한 문제에 직면했습니다. 위의 솔루션의 구문과 제한 사항이 마음에 들지 않았기 때문에 Go에서 작업을 수행하는 프로그램을 신속하게 정리했습니다.

여기에서 도구를 확인할 수 있습니다 : preftime

GitHub 프로젝트 의 릴리스 섹션에는 Linux, MacOS 및 Windows 용으로 사전 빌드 된 실행 파일 이 있습니다.

이 도구는 불완전한 출력 라인을 처리하고 (내 견해로는)보다 간결한 구문을 가지고 있습니다.

<command> | preftime

이상적이지는 않지만 누군가를 도울 수 있도록 공유하고 싶지는 않습니다.


0

으로 그 일을 date하고 trxargsOSX에 :

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

당신이 밀리 초를 원한다면 :

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

그러나 OSX에서 date는 % N 옵션을 제공하지 않으므로 gdate ( brew install coreutils) 를 설치해야 하므로 마지막으로 다음에 도달하십시오.

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

-1

앞에 붙는 값이 모든 줄에서 동일하면 파일과 함께 emacs를 시작하십시오.

Ctrl + <space>

파일의 시작 부분에서 (그 자리를 표시하기 위해) 마지막 줄의 시작 부분으로 아래로 스크롤하십시오 (Alt +>는 파일의 끝으로 이동합니다 ... 아마도 Shift 키가 필요할 것입니다. + a를 누르면 해당 줄의 시작 부분으로 이동합니다.

Ctrl + x r t

방금 지정한 사각형 (0 너비의 사각형)에 삽입하는 명령입니다.

2008-8-21 6:45 PM <입력>

또는 앞에 붙일 항목이 있으면 너비가 0 인 사각형의 모든 줄 앞에 텍스트가 붙는 것을 볼 수 있습니다.

업데이트 : 나는 당신이 같은 날짜를 원하지 않는다는 것을 깨달았습니다. 그래서 이것은 작동하지 않을 것입니다. 알아두면 좋겠다 ...

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.