명령의 각 출력 줄에 타임 스탬프를 추가하고 싶습니다. 예를 들면 다음과 같습니다.
foo
bar
baz
될 것이다
[2011-12-13 12:20:38] foo
[2011-12-13 12:21:32] bar
[2011-12-13 12:22:20] baz
… 접두사가 붙는 시간은 라인이 인쇄 된 시간입니다. 어떻게하면 되나요?
답변
moreutils 에는 다음 ts
과 같은 기능이 포함되어 있습니다 .
command | ts '[%Y-%m-%d %H:%M:%S]'
또한 루프가 필요 없으며 모든 출력 라인에는 타임 스탬프가 붙습니다.
$ echo -e "foo\nbar\nbaz" | ts '[%Y-%m-%d %H:%M:%S]'
[2011-12-13 22:07:03] foo
[2011-12-13 22:07:03] bar
[2011-12-13 22:07:03] baz
서버가 언제 다시 시작되었는지 알고 싶습니까? 그냥 실행 ping | ts
, 문제 해결 : D.
답변
첫째, 이러한 타임 스탬프가 실제로 이벤트를 나타낼 것으로 예상되는 경우 많은 프로그램이 라인 버퍼링을 수행하기 때문에 (다른 것보다 더 적극적으로),이를 원래 라인의 시간에 가깝게 생각하는 것이 중요합니다. 액션 타임 스탬프가 아닌 인쇄되었습니다.
명령에 이미 내장 기능이 없는지 확인하고 싶을 수도 있습니다. 예를 들어, ping -D
일부 ping
버전에 존재하며 각 라인 앞에 유닉스 시대 이후의 시간을 인쇄합니다. 그러나 명령에 고유 한 방법이 포함되어 있지 않은 경우 사용할 수있는 몇 가지 방법과 도구가 있습니다.
POSIX 쉘
많은 쉘이 문자열을 내부적으로 cstring으로 저장하므로 입력에 널 문자 ( \0
) 가 포함되어 있으면 행이 조기에 종료 될 수 있습니다.
command | while IFS= read -r line; do printf '[%s] %s\n' "$(date '+%Y-%m-%d %H:%M:%S')" "$line"; done
GNU awk
command | gawk '{ print strftime("[%Y-%m-%d %H:%M:%S]"), $0 }'
펄
command | perl -pe 'use POSIX strftime; print strftime "[%Y-%m-%d %H:%M:%S] ", localtime'
파이썬
command | python -c 'import sys,time;sys.stdout.write("".join(( " ".join((time.strftime("[%Y-%m-%d %H:%M:%S]", time.localtime()), line)) for line in sys.stdin )))'
루비
command | ruby -pe 'print Time.now.strftime("[%Y-%m-%d %H:%M:%S] ")'
답변
라인 별 델타 측정의 경우 gnomon을 시도하십시오 .
타임 스탬프 정보를 다른 명령의 표준 출력에 추가하는 것은 moreutils의 ts와 비슷한 명령 행 유틸리티입니다. 오래 걸리는 것에 대한 역사적 기록을 원하는 장기 실행 프로세스에 유용합니다.
gnomon에 아무것도 파이프하면 각 라인에 타임 스탬프가 추가되어 해당 라인이 버퍼의 마지막 라인이었던 시간, 즉 다음 라인이 나타나는 데 걸린 시간을 나타냅니다. 기본적으로 gnomon은 각 줄 사이에 경과 된 초를 표시하지만 구성 할 수 있습니다.
답변
Ryan의 게시물은 흥미로운 아이디어를 제공하지만 여러 측면에서 실패합니다. 로 테스트하는 동안 나중에 초 단위로 차이가 tail -f /var/log/syslog | xargs -L 1 echo $(date +'[%Y-%m-%d %H:%M:%S]') $1
나는 경우에도 타임 스탬프가 동일하게 유지됩니다 stdout
. 이 출력을 고려하십시오.
[2016-07-14 01:44:25] Jul 14 01:44:32 eagle dhclient[16091]: DHCPREQUEST of 192.168.0.78 on wlan7 to 255.255.255.255 port 67 (xid=0x411b8c21)
[2016-07-14 01:44:25] Jul 14 01:44:34 eagle avahi-daemon[740]: Joining mDNS multicast group on interface wlan7.IPv6 with address fe80::d253:49ff:fe3d:53fd.
[2016-07-14 01:44:25] Jul 14 01:44:34 eagle avahi-daemon[740]: New relevant interface wlan7.IPv6 for mDNS.
내 제안 된 솔루션은 비슷하지만 적절한 타임 스탬핑을 제공하고보다 휴대 성 printf
이 더 높습니다.echo
| xargs -L 1 bash -c 'printf "[%s] %s\n" "$(date +%Y-%m-%d\ %H:%M:%S )" "$*" ' bash
왜 bash -c '...' bash
? -c
옵션 으로 인해 첫 번째 인수가 $0
출력에 지정되고 출력에 표시되지 않습니다. 적절한 설명은 쉘 매뉴얼 페이지를 참조하십시오-c
tail -f /var/log/syslog
내 무선 랜에 연결을 끊었다가 다시 연결 하여이 솔루션을 테스트하면 메시지 date
와 syslog
메시지 모두에서 올바른 타임 스탬프가 표시됩니다.
배쉬는 bourne 같은 쉘로 대체 될 수 있으며 적어도 옵션 이있는 쉘로 ksh
또는 으로 수행 할 수 있습니다 .dash
-c
잠재적 인 문제 :
이 솔루션에는 xargs
POSIX 호환 시스템에서 사용할 수있는가 있어야하므로 대부분의 유닉스 계열 시스템이 포함되어야합니다. 시스템이 POSIX 호환이 아니거나 시스템이 없으면 작동하지 않습니다.GNU findutils
답변
나는 위에서 언급하는 것을 선호했지만 평판으로는 말할 수 없습니다. 어쨌든 위의 Perl 샘플은 다음과 같이 버퍼링되지 않을 수 있습니다.
command | perl -pe 'use POSIX strftime;
$|=1;
select((select(STDERR), $| = 1)[0]);
print strftime "[%Y-%m-%d %H:%M:%S] ", localtime'
첫 번째 ‘$ |’ STDOUT의 버퍼를 해제합니다. 두 번째는 stderr을 현재 기본 출력 채널로 설정하고 버퍼링을 해제합니다. select는 select를 원래 안에 래핑함으로써 $ |의 원래 설정을 반환하므로 $ |도 재설정합니다. 기본값 인 STDOUT으로 설정하십시오.
그리고 네, 페이스트를 그대로자를 수 있습니다. 가독성을 위해 여러 줄로 표시했습니다.
그리고 정말로 정확하게 알고 싶다면 Time :: Hires가 설치되어 있습니다.
command | perl -pe 'use POSIX strftime; use Time::HiRes gettimeofday;
$|=1;
select((select(STDERR), $| = 1)[0]);
($s,$ms)=gettimeofday();
$ms=substr(q(000000) . $ms,-6);
print strftime "[%Y-%m-%d %H:%M:%S.$ms]", localtime($s)'
답변
대부분의 답변은을 사용하는 것이 date
좋지만 속도가 느립니다. bash 버전이 4.2.0보다 큰 경우 printf
대신 bash 를 사용 하는 것이 좋습니다 . 레거시 bash 버전을 지원해야하는 경우 bash 버전에 log
따라 함수 를 작성할 수 있습니다 .
TIMESTAMP_FORMAT='%Y-%m-%dT%H:%M:%S'
# Bash version in numbers like 4003046, where 4 is major version, 003 is minor, 046 is subminor.
printf -v BV '%d%03d%03d' ${BASH_VERSINFO[0]} ${BASH_VERSINFO[1]} ${BASH_VERSINFO[2]}
if ((BV > 4002000)); then
log() {
## Fast (builtin) but sec is min sample for most implementations
printf "%(${TIMESTAMP_FORMAT})T %5d %s\n" '-1' $$ "$*" # %b convert escapes, %s print as is
}
else
log() {
## Slow (subshell, date) but support nanoseconds and legacy bash versions
echo "$(date +"${TIMESTAMP_FORMAT}") $$ $*"
}
fi
속도 차이를보십시오 :
user@host:~$time for i in {1..10000}; do printf "%(${TIMESTAMP_FORMAT})T %s\n" '-1' "Some text" >/dev/null; done
real 0m0.410s
user 0m0.272s
sys 0m0.096s
user@host:~$time for i in {1..10000}; do echo "$(date +"${TIMESTAMP_FORMAT}") Some text" >/dev/null; done
real 0m27.377s
user 0m1.404s
sys 0m5.432s
UPD : 대신 $(date +"${TIMESTAMP_FORMAT}")
그것을 사용하는 것이 좋습니다 $(exec date +"${TIMESTAMP_FORMAT}")
또는 $(exec -c date +"${TIMESTAMP_FORMAT}")
너무 실행 속도를 높이는.
답변
당신은이 작업을 수행 할 수 있습니다 date
및 xargs
:
... | xargs -L 1 echo `date +'[%Y-%m-%d %H:%M:%S]'` $1
설명:
xargs -L 1
xargs에게 1 행의 입력마다 진행 명령을 실행하도록 지시하고, 첫 번째 행을 통과합니다. echo `date +'[%Y-%m-%d %H:%M:%S]'` $1
기본적으로 마지막에 입력 인수로 날짜를 에코합니다.