명령의 각 출력 라인에 타임 스탬프를 추가하고 싶습니다. 예 :
foo bar baz
는
[2011-12-13 12:20:38] foo [2011-12-13 12:21:32] bar [2011-12-13 12:22:20] baz
… 접두사는 라인이 인쇄 된 시간입니다. 어떻게해야합니까?
댓글
- 타임 스탬프를 앞에 추가하는 Unix 유틸리티가 있습니까? stdin?
답변
moreutils 에는 ts
가 포함되어 있습니다.
command | ts "[%Y-%m-%d %H:%M:%S]"
It 루프도 필요하지 않으며 모든 출력 라인에는 타임 스탬프가 있습니다.
$ 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.
댓글
- 어떻게이 사실을 알 수 없었습니까? ?!?!?! 이것은 놀랍게도 tail -f를 보완합니다!
tail -f /tmp/script.results.txt | ts
- ts 명령이 없으면 ‘ 무엇을 사용해야합니까?
- ‘ 작동하지 않는 경우 stderr를 stdout으로 리디렉션 해보십시오.
ssh -v 127.0.0.1 2>&1 | ts
- Debian에서
sudo apt install moreutils
를 수행하고 다음에서yum install moreutils
를 수행하여 설치합니다. Fedora. -
-s
매개 변수를 지적하는 것이 유용하다고 생각합니다. 명령의 런타임을 표시합니다. 저는 개인적으로ts
와ts -s
를 동시에 사용하는 것을 좋아합니다. 다음과 같은 형식입니다 :command | ts -s '(%H:%M:%.S)]' | ts '[%Y-%m-%d %H:%M:%S'
. 다음과 같은 로그 행이 앞에 추가됩니다.[2018-12-04 08:31:00 (00:26:28.267126)] Hai <3
Answer
첫째, 이러한 타임 스탬프가 실제로 이벤트를 나타낼 것으로 예상하는 경우 많은 프로그램이 라인 버퍼링을 수행하기 때문에 (일부는 다른 프로그램보다 공격적으로)이를 원래 라인이 수행하는 시간에 가깝다고 생각하는 것이 중요합니다. 실행중인 작업의 타임 스탬프가 아니라 인쇄되었습니다.
또한 명령에이 작업을 수행하는 전용 내장 기능이 없는지 확인할 수도 있습니다. 예를 들면 ping -D
는 일부 ping
버전에 존재하며 각 줄 앞에 Unix 시대 이후의 시간을 인쇄합니다. 그러나 명령에 자체 메서드가 포함되어 있지 않은 경우 다음과 같은 몇 가지 방법과 도구를 사용할 수 있습니다.
POSIX shell
입력에 null이 포함 된 경우 많은 셸이 문자열을 내부적으로 cstring으로 저장하므로 숯 acter (\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 }"
Perl
command | perl -pe "use POSIX strftime; print strftime "[%Y-%m-%d %H:%M:%S] ", localtime"
Python
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 )))"
Ruby
command | ruby -pe "print Time.now.strftime("[%Y-%m-%d %H:%M:%S] ")"
댓글
- 여기서 한 가지 문제는 많은 프로그램이 켜져 있다는 것입니다. stdout이 터미널이 아닌 파이프 일 때 더 많은 출력 버퍼링.
- @cjm-True. 일부 출력 버퍼링은
stdbuf -o 0
를 사용하여 완화 할 수 있지만 프로그램이 출력 버퍼링을 수동으로 처리하는 경우 ‘ 출력 버퍼의 크기를 비활성화 / 축소하는 옵션이 있습니다. - python의 경우
python -u
- @Bwmat No.
... for x in sys.stdin
는 먼저 메모리에 모두 버퍼링하지 않고 행을 반복합니다. - 이 작업을 수행하면 버퍼링이 발생합니다 … for a in 1 1 1 1 1; 수면 1; 에코; 완료 | python -c ‘ import sys, time; sys.stdout.write (” ” .join ((” ” .join ((time.strftime (” [% Y- % m- % d % H : % M : % S] “, time.gmtime ()), line)) for sys.stdin))) ‘
답변
라인 별 델타 측정의 경우 , gnomon 을 사용해보세요.
moreutils와 비슷한 명령 줄 유틸리티입니다. “s ts, 다른 명령의 표준 출력에 타임 스탬프 정보를 추가합니다. 시간이 오래 걸리는 항목에 대한 기록 기록을 원하는 장기 실행 프로세스에 유용합니다.
gnomon에 무엇이든 파이핑하면됩니다. 각 줄 앞에 타임 스탬프를 추가하여 해당 줄이 버퍼의 마지막 줄이었던 시간, 즉 다음 줄이 나타나는 데 걸린 시간을 나타냅니다. 기본적으로 gnomon은 경과 된 시간 (초)을 표시합니다. 각 줄 사이에 있지만 구성 할 수 있습니다.
댓글
- 라이브 프로세스를 사용할 때
ts
에 대한 훌륭한 대안처럼 보입니다.ts
는 비대화 형 프로세스에 더 적합합니다.
답변
위에 댓글을 달고 싶었지만 평판 적으로는 할 수 없습니다. 어쨌든 위의 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)"
댓글
- 비표준 패키지를 설치하지 않고도 매력처럼 작동합니다.
답변
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.
제안 된 솔루션은 유사하지만 적절한 타임 스탬프를 제공하고 다소 이식성이 뛰어납니다. echo
가 아닌 printf
| xargs -L 1 bash -c "printf "[%s] %s\n" "$(date +%Y-%m-%d\ %H:%M:%S )" "$*" " bash
이유 bash -c "..." bash
? -c
옵션으로 인해 첫 번째 인수가 nt는 $0
에 할당되고 출력에 표시되지 않습니다. -c
tail -f /var/log/syslog
를 사용하여이 솔루션 테스트에 대한 올바른 설명은 쉘의 매뉴얼 페이지를 참조하십시오. 추측 할 수있을 것입니다. Wi-Fi 연결을 끊었다가 다시 연결하면 date
및 syslog
메시지
에서 제공하는 적절한 타임 스탬프가 표시됩니다. p>
Bash는 bourne-like shell로 대체 할 수 있으며, ksh
또는 dash
중 하나를 사용하여 수행 할 수 있습니다. -c
옵션이 있습니다.
잠재적 문제 :
해결 방법에는 xargs
가 있어야합니다. POSIX 호환 시스템에서 사용할 수 있으므로 대부분의 Unix 계열 시스템을 다루어야합니다. 시스템이 POSIX를 준수하지 않거나 GNU findutils
가 없으면 분명히 “작동하지 않습니다.” p>
답변
대부분의 답변은 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 -c date +"${TIMESTAMP_FORMAT}")
실행 속도가 너무 빨라졌습니다.
UPD2 : bash 5는 마이크로 초 동안 EPOCHREALTIME
변수를 제공합니다. 다음 명령으로 사용할 수 있습니다 (초보다 약 30 % 느림). printf "%(${TIMESTAMP_FORMAT})T.%s %5d %s\n" ${EPOCHREALTIME/./ } $$ "$*"
댓글
- 이 답변은 매우 과소 평가되었습니다. 특히 상대적인 성능 영향을 보여 주면 좋습니다.
- 훌륭한 제안이지만 안타깝게도 날짜는 1 초 미만의 해상도를 제공하지 않습니다. 이는 제 경우에 요구되는 사항입니다.
- bash 5.0 이상에서는 다음 명령을 사용할 수 있습니다.
printf "%(${TIMESTAMP_FORMAT})T.%s %5d %s\n" ${EPOCHREALTIME/./ } $$ "$*"
Answer
및 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
는 기본적으로 끝에 입력 인수가있는 날짜를 표시합니다.
댓글
- 해결 방법 가깝지만 긴 시간으로 구분 된 출력의 경우 ‘ 제대로 타임 스탬프가 표시되지 않습니다. 또한 ‘ 백틱을 사용하고 있으며 ‘ 따옴표로 묶지 않았습니다
$1
. 그 ‘ 스타일이 좋지 않습니다. 항상 변수를 인용하십시오. 또한 ‘ 휴대용이 아닌echo
를 사용하고 있습니다. ‘ 괜찮지 만 일부 시스템에서는 제대로 작동하지 않을 수 있습니다. - 이를 테스트 한 결과 ‘ 정말 옳은 것으로 보입니다 …
date
모든 줄을 재평가 받습니까, 아니면 거의 절망적입니까?
답변
무언가를위한 뻔뻔한 플러그 이 정확한 문제를 해결하기 위해 작성했습니다. ets
, Go로 작성되었습니다.
프로젝트 페이지에서 많은 사용 예를 찾을 수 있습니다.
기존 답변 및 유사 제품과의 눈에 띄는 차이점은 ets
가 pty (의사 tty)로 명령을 실행하도록 설계되었다는 것입니다. 즉, 시뮬레이션 tty에서 기본적으로 실행되는 명령. 예를 들어 배관 명령 출력과 비교 ts
, 이것은 타임 스탬프를 대부분 투명하게 만들고 여러 가지 파이프 문제를 해결합니다.
- 일부 프로그램은 파이프에 쓸 때 공격적으로 버퍼링하므로 출력이 표시되지 않은 다음 전체 출력이 표시됩니다 (예, stdbuf 할 수 있습니다. stdbuf 및 ts를 별칭 / 함수로 래핑 할 수도 있지만 기본적으로 작동하면 더 좋지 않을 것입니다.)
- 일부 프로그램은 파이프에 쓸 때 색상 및 / 또는 상호 작용을 비활성화합니다.
- pipefail을 설정하지 않으면 종료 상태가 사라집니다.
명령은 직접 실행됩니다. 즉, 기존 명령 줄 앞에 ets
를 추가하거나 셸 명령 (위의 gif 참조) 일 수 있습니다. 물론 출력을 파이프로 연결하려면 ets
도 가능합니다.
ets
는 동일한 기능을 지원합니다. moreutils ts
와 같은 타임 스탬프 모드 : 절대 시간 모드, 경과 시간 모드 및 증분 시간 모드. 더 건전한 기본값을 사용하고 (예 : 단조 시계는 항상 경과 / 증분 타임 스탬프에 사용됨) 사용자 지정 시간대에 대한 추가 지원이 있습니다. 자세한 비교는 여기 입니다.
다시, https://github.com/zmwangx/ets . 시도해보고 버그를 신고하세요.
답변
입력 스크립트 시작 부분 근처
# prepend a timestamp to all output exec &> >( ts "%Y-%m-%d.%H%M.%.S " )
또는 추가 크레딧을 받으려면 다음을 통해 로그 파일로 출력하세요.
script_name=foobar log_file=$( printf "/tmp/${script_name}-%(%Y-%m-%d)T.%(%H%M%S)T.log" -1 ) echo "note: redirecting output to [${log_file}]" exec &> >( ts "%Y-%m-%d %H:%M:%.S " > ${log_file} )
콘솔과 로그 파일 모두에 출력 :
script_name=foobar log_file=$( printf "/tmp/${script_name}-%(%Y-%m-%d)T.%(%H%M%S)T.log" -1 ) exec &> >( ts "%Y-%m-%d %H:%M:%.S " | tee ${log_file} )
이 작업의 주요 이점은 로깅을 다른 모든 것과 분리하는 것입니다. 모든 명령에 대해 tee
또는 이와 유사한 방식으로 파이핑하여 스크립트 본문을 복잡하게 만들고 사용자 지정 로깅 함수를 작성하지 않고 평범한 이전 echo
.
ts
프로그램은 moreutils
패키지에서 찾을 수 있습니다. 건전한 행정 체제. 🙂