답변:
$ cat input.log | sed -e "s/^/$(date -R) /" >> output.log
작동 방식 :
cat
호출 된 파일을 읽고 input.log
표준 출력 스트림으로 인쇄합니다.
일반적으로 표준 출력은 터미널에 연결되어 있지만이 작은 스크립트에는 |
쉘이 표준 출력 cat
을의 표준 입력으로 리디렉션합니다 sed
.
sed
옵션 cat
과 함께 제공된 스크립트에 따라 데이터를 읽고 처리 -e
한 다음 표준 출력으로 인쇄합니다. 이 스크립트 "s/^/$(date -R) /"
는 모든 줄의 시작을 date -R
명령에 의해 생성 된 텍스트로 바꾸는 것을 의미합니다 (바꾸기 명령의 일반적인 구성은 다음과 같습니다 s/pattern/replace/
).
그런 다음에 따르면 파일 >>
bash
의 출력 을 리디렉션합니다 ( 파일 내용 바꾸기 및 끝에 추가하는 것을 의미 함).sed
output.log
>
>>
문제는 $(date -R)
스크립트를 실행할 때 한 번 평가되므로 각 줄의 시작 부분에 현재 타임 스탬프 가 삽입 됩니다. 현재 타임 스탬프는 메시지가 생성 된 순간과는 거리가 멀 수 있습니다. 이를 피하려면 cron 작업이 아닌 파일에 메시지를 쓸 때 메시지를 처리해야합니다.
위에서 설명한 표준 스트림 리디렉션은 pipe 라고 합니다. |
스크립트의 명령 사이뿐만 아니라 FIFO 파일 (일명 pipe )을 통해 리디렉션 할 수 있습니다 . 한 프로그램은 파일에 쓰고 다른 프로그램은 데이터를 읽고 첫 번째 전송으로 수신합니다.
예를 선택하십시오.
$ mkfifo foo.log.fifo
$ while true; do cat foo.log.fifo | sed -e "s/^/$(date -R) /" >> foo.log; done;
# have to open a second terminal at this point
$ echo "foo" > foo.log.fifo
$ echo "bar" > foo.log.fifo
$ echo "baz" > foo.log.fifo
$ cat foo.log
Tue, 20 Nov 2012 15:32:56 +0400 foo
Tue, 20 Nov 2012 15:33:27 +0400 bar
Tue, 20 Nov 2012 15:33:30 +0400 baz
작동 방식 :
mkfifo
명명 된 파이프를 만듭니다.
while true; do sed ... ; done
무한 루프를 실행하고 모든 반복에서 표준 입력 sed
으로 리디렉션 foo.log.fifo
하여 실행됩니다 . sed
입력 데이터 대기를 차단 한 다음 수신 된 메시지를 처리하여로 리디렉션 된 표준 출력으로 인쇄합니다 foo.log
.
루프가 현재 터미널을 차지하므로이 시점에서 새 터미널 창을 열어야합니다.
echo ... > foo.log.fifo
fifo 파일로 경로 재 지정된 표준 출력으로 메시지를 인쇄하고 sed
이를 수신하여 처리하고 일반 파일에 씁니다.
중요한 점은 측면 중 하나가 프로세스에 연결되어 있지 않으면 다른 파이프가 의미가없는 것처럼 fifo입니다. 파이프에 쓰려고하면 누군가 파이프의 다른 쪽에서 데이터를 읽을 때까지 현재 프로세스가 차단 됩니다 . 파이프에서 읽으려면 누군가 파이프에 데이터를 쓸 때까지 프로세스가 차단 됩니다. sed
당신이 할 때까지 예를 루프 위에 아무것도 (잠을) 않습니다 echo
.
특정 상황에서는 fifo 파일에 로그 메시지를 쓰도록 응용 프로그램을 구성하기 만하면됩니다. 구성 할 수없는 경우 원본 로그 파일을 삭제하고 fifo 파일을 만드십시오. 그러나 sed
어떤 이유로 루프가 죽으면 write
파일을 누군가가 read
fifo에서 나올 때까지 파일 을 시도 할 때 프로그램이 차단됩니다 .
장점은 프로그램에서 파일에 쓸 때 현재 타임 스탬프가 평가되어 메시지에 첨부되는 것입니다.
tailf
로그에 기록하고보다 독립적으로 처리하기 위해와 함께 두 개의 일반 파일을 사용할 수 있습니다 tailf
. 응용 프로그램은 원시 파일에 메시지를 쓰고 다른 프로세스는 새 줄을 읽고 (비동기 적으로 씁니다) 두 번째 파일에 쓰면서 데이터를 처리합니다.
예를 들어 보자.
# will occupy current shell
$ tailf -n0 bar.raw.log | while read line; do echo "$(date -R) $line" >> bar.log; done;
$ echo "foo" >> bar.raw.log
$ echo "bar" >> bar.raw.log
$ echo "baz" >> bar.raw.log
$ cat bar.log
Wed, 21 Nov 2012 16:15:33 +0400 foo
Wed, 21 Nov 2012 16:15:36 +0400 bar
Wed, 21 Nov 2012 16:15:39 +0400 baz
작동 방식 :
tailf
쓰기를 수행 bar.raw.log
하고 무한 while read ... echo
루프로 리디렉션 된 표준 출력으로 인쇄하는 프로세스를 실행 합니다 . 이 루프는 표준 입력에서 호출 된 버퍼 변수로 데이터를 읽은 line
다음 생성 된 타임 스탬프를 다음 버퍼링 된 데이터와 함께에 기록합니다 bar.log
.
에 메시지를 작성하십시오 bar.raw.log
. tailf
쓰기 작업을 수행하고 작업을 수행 하는 첫 번째 터미널이 점유되므로 별도의 터미널 창에서이 작업을 수행해야합니다. 아주 간단합니다.
장점은 당신이 죽이면 응용 프로그램이 차단되지 않을 것 tailf
입니다. 단점은 덜 정확한 타임 스탬프 및 복제 로그 파일입니다.
tailf
하고 올바른 사용법을 추가했습니다. 실제로와 함께하는 방법 tailf
이 더 우아해 보이지만 나는 fifo를 떠나 누군가에게 유용 할 수 있기를 바랍니다.
Dmitry Vasilyanov의 답변에서 수정되었습니다.
bash 스크립트에서는 타임 스탬프를 사용하여 출력을 한 줄씩 재지 정하고 줄 바꿈 할 수 있습니다.
사용시기 :
tailf
Dmitry Vasilyanov가 말한 것처럼 로그 파일 에 사용 하는 것이 좋습니다 .예를 들면 foo.sh
:
#!/bin/bash
exec &> >(while read line; do echo "$(date +'%h %d %H:%M:%S') $line" >> foo.log; done;)
echo "foo"
sleep 1
echo "bar" >&2
sleep 1
echo "foobar"
그리고 결과 :
$ bash foo.sh
$ cat foo.log
May 12 20:04:11 foo
May 12 20:04:12 bar
May 12 20:04:13 foobar
작동 원리
exec &>
stdout 및 stderr를 동일한 위치로 리디렉션>( ... )
파이프 출력을 비동기 내부 명령으로예를 들면 다음과 같습니다.
파이프 타임 스탬프 및 파일에 로그
#!/bin/bash
exec &> >(while read line; do echo "$(date +'%h %d %H:%M:%S') $line" >> foo.log; done;)
echo "some script commands"
/path-to/some-thrid-party-programs
또는 타임 스탬프를 인쇄하고 stdout에 기록
#!/bin/bash
exec &> >(while read line; do echo "$(date +'%h %d %H:%M:%S') $line"; done;)
echo "some script commands"
/path-to/some-thrid-party-programs
그런 다음 /etc/crontab
설정에 저장하십시오.
* * * * * root /path-to-script/foo.sh >> /path-to-log-file/foo.log
내가 사용하는 ts
내가 선인장 원격 호스트의 통계를 가득 얻을하는 데 사용하는 스크립트에 대한 오류 로그의 시간 스탬프 항목을 얻기 위해 이런 식으로.
Cacti를 테스트 rand
하기 위해 시스템 온도를 모니터링하기 위해 온도 그래프에 사용하는 임의의 값을 추가합니다.
Pushmonstats.sh는 내 PC의 시스템 온도 통계를 수집하여 Cacti가 실행되는 Raspberry Pi로 전송하는 스크립트입니다. 얼마 전에 네트워크가 중단되었습니다. 오류 로그에 SSH 시간 초과가 발생했습니다. 불행히도, 해당 로그에 시간 항목이 없습니다. 로그 항목에 타임 스탬프를 추가하는 방법을 몰랐습니다. 그래서 인터넷에서 검색을 한 후이 게시물을 우연히 발견했으며 이것이 내가 사용 한 것 ts
입니다.
그것을 테스트하기 위해 알 수없는 옵션을 사용했습니다 rand
. stderr에 오류가 발생했습니다. 이를 캡처하기 위해 임시 파일로 리디렉션합니다. 그런 다음 cat을 사용하여 파일의 내용을 표시하고로 파이프 ts
하고이 게시물에서 찾은 시간 형식을 추가하고 오류 파일에 기록합니다. 그런 다음 임시 파일의 내용을 지우십시오. 그렇지 않으면 동일한 오류에 대한 이중 항목이 나타납니다.
크론 탭 :
* * * * * /home/monusr/bin/pushmonstats.sh 1>> /home/monusr/pushmonstats.log 2> /home/monusr/.err;/bin/cat /home/monusr/.err|/usr/bin/ts %F-%H:%M:%.S 1>> /home/monusr/pushmonstats.err;> /home/monusr/.err
이것은 내 오류 로그에 다음을 제공합니다.
2014-03-22-19:17:53.823720 rand: unknown option -- '-l'
어쩌면 이것이 매우 우아한 방법은 아니지만 효과가 있습니다. 더 우아한 접근 방식이 있는지 궁금합니다.