로그 파일이 있고 각 줄이 추가될 때마다 타임스탬프를 추가해야 합니다. 그래서 저는 로그 줄의 각 항목에 타임스탬프를 추가하고 cron 작업으로 실행할 수 있는 스크립트를 찾고 있습니다.
답변1
일반적인 방법
$ 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 작업을 사용하는 대신 메시지가 파일에 기록될 때 처리해야 합니다.
선입선출
위에 설명된 표준 스트림 리디렉션은 다음과 같습니다.관로. 스크립트의 명령 간에 리디렉션 할 수 있을 뿐만 아니라 다음을 |
통해 리디렉션할 수도 있습니다.선입선출 파일(일명명명된 파이프). 한 프로그램은 파일에 쓰고 다른 프로그램은 데이터를 읽고 처음 전송될 때 이를 수신합니다.
예시를 선택하세요:
$ 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
어떤 이유로 루프가 종료 되면 누군가가 fifo에서 파일에 액세스할 write
때까지 파일에 액세스하려고 시도하는 프로그램이 차단됩니다 .read
혜택은현재의프로그램이 파일에 메시지를 쓸 때 타임스탬프가 평가되어 메시지에 추가됩니다.
비동기 처리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
. 단점은 덜 정확한 타임스탬프와 중복된 로그 파일입니다.
답변2
ts
Perl 스크립트를 사용할 수 있습니다moreutils
:
$ echo test | ts %F-%H:%M:%.S
2012-11-20-13:34:10.731562 test
답변3
Dmitry Vasilyanov의 답변이 수정되었습니다.
Bash 스크립트에서는 타임스탬프를 사용하여 출력을 한 줄씩 리디렉션하고 래핑할 수 있습니다.
사용 시기:
- Bash 스크립트 작업의 경우 기본 스크립트 앞에 이 줄을 삽입하세요.
- 비스크립트 작업의 경우 프로그램을 호출하는 스크립트를 만듭니다.
tailf
시스템 서비스 제어를 위해서는 Dmitry Vasilianov가 말했듯이 로그 파일을 사용하는 것이 좋습니다 .
다음은 다음과 같은 예입니다 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을 동일한 위치로 리디렉션>( ... )
비동기 내부 명령으로 출력 파이프- 나머지는 Dmitry Vasilyanov가 설명한 대로 작동합니다.
예를 들어:
타임스탬프와 로그를 파일로 파이프
#!/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
또는 타임스탬프를 인쇄하고 표준 출력에 기록합니다.
#!/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
답변4
나는 ts
이 방법을 사용하여 오류 로그에서 타임스탬프된 항목을 가져오고 스크립트는 Cacti를 가져오고 원격 호스트의 통계를 채우는 데 사용됩니다.
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'
아마도 이것은 매우 우아한 접근 방식은 아니지만 작동합니다. 좀 더 우아한 방법이 있는지 궁금합니다.