FIFO를 통해 로그인 한 다음 파일로 리디렉션 하시겠습니까?


8

각 트랜잭션을 기록해야하는 응용 프로그램이 있습니다. 충돌을 일으키는 원인에 대한 기록이 필요하기 때문에 모든 로그 메시지가 플러시됩니다. 동료들과 나는 로그 메시지가 프로세스를 벗어나도록 보장하면서 버퍼링의 성능 효과를 얻는 방법에 대해 궁금했습니다.

우리가 생각 해낸 것은 :

  • 응용 프로그램이 쓸 수있는 FIFO를 만들고
  • 를 통해 해당 FIFO의 내용을 일반 파일로 리디렉션합니다 cat.

즉, 일반적으로 무엇입니까 :

app --logfile logfile.txt

지금 :

mkfifo logfifo
cat logfifo &> logfile.txt &
app --logfile logfifo

이 접근 방식에 문제가 있습니까? 테스트 할 때 효과가 있었지만 원래 응용 프로그램이 충돌하더라도 메시지가 경로 재 지정 파일로 이동하는지 확인하고 싶습니다.

(우리는 응용 프로그램에 대한 소스 코드가 없으므로 프로그래밍 솔루션에 대해서는 의문의 여지가 없습니다. 또한 응용 프로그램에 쓰지 stdout않으므로 다른 명령에 직접 파이핑하는 것은 문제 syslog가 아닙니다 . .)


업데이트 : 현상금을 추가했습니다. 허용 대답은 할 수 없습니다 포함 logger간단한의 이유 logger입니다 하지 나에 대해 질문 한 내용. 원래 질문에서 알 수 있듯이 FIFO를 사용할 때만 문제를 찾고 있습니다.


지금까지 몇 가지 답변에 엄청난 혼란이있는 것 같습니다. 필자의 질문에서 처음 강조한 것처럼 FIFO를 로깅 중개자로 사용하는 방법에 대한 문제를 찾고 있습니다. 나는 내 원래 질문 의 단점 을 탐색하지 않는 대체 제안에 관심이 없습니다 .
chrisaycock

stdout에 로깅에 대한 내 대답이 관심있는 방향이 아닌 경우 "응용 프로그램이 stdout에 쓰지 않으므로 다른 명령으로 직접 파이프하는 것이 문제가 아닙니다"를 제거 할 수 있습니까?
nickgrim

답변:


6

fifo는 일반적으로 쓰여진 양이 읽은 양을 초과 할 수있는 프로그래밍에 필요합니다.

이러한 fifo는 예상대로 완벽하게 작동하지 않지만 다른 문제를 소개하면서 주요 문제를 해결할 것입니다.

세 가지 가능한 경고가 있습니다.

  1. 초기화시 다른 쪽 끝을 읽는 것이 없으면 fifo에 쓰기가 무기한 차단됩니다.
  2. fifo의 고정 폭은 64K로, 버퍼가 해당 지점에 의해 채워지면 리더가 따라 올 때까지 추가 쓰기가 차단됩니다.
  3. 독자가 죽거나 나가면 파이프 라이터는 SIGPIPE로 사망합니다.

이는 문제 (버퍼링되지 않은 쓰기에서 버퍼링 된 I / O 에뮬레이션)가 해결됨을 의미합니다. 이는 FIFO의 새로운 '제한'이 실제로 파이프에 디스크에있는 내용 (버퍼 입출력이 버퍼링 됨)에 쓰는 유틸리티의 속도가되기 때문입니다.

그럼에도 불구하고 기록기는 작동하기 위해 로그 리더에 의존합니다. 독자가 갑자기 읽는 것을 멈 추면 작가가 차단합니다. 판독기가 갑자기 종료되면 (대상의 디스크 공간이 부족하다고 말하면) 기록기가 SIGPIPE하고 종료 될 수 있습니다.

언급해야 할 또 다른 요점은 서버 패닉과 커널의 응답이 중지되면 해당 버퍼에있는 최대 64k의 데이터가 손실 될 수 있다는 것입니다.

이 문제를 해결하는 또 다른 방법은 로그를 tmpfs (Linux의 경우 / dev / shm)에 기록하고 출력을 고정 디스크 위치에 맞추는 것입니다. 이 작업을 수행하는 메모리 할당에는 제한이 적지 만 (64K가 아니라 일반적으로 2G!) 기록기가 동적으로 로그 파일을 다시 열 수있는 방법이없는 경우에는 작동하지 않을 수 있습니다 (tmpfs에서 정기적으로 로그를 정리해야 함). 이 방법으로 서버 패닉이 발생하면 많은 데이터가 손실 될 수 있습니다.


에 관한 좋은 정보 /dev/shm입니다. 우리는 그것을 사용하기 위해 마음을 미끄러 뜨 렸지만 그것을 고려했습니다 tail -f.
chrisaycock

4
mkfifo logfifo
cat logfifo &> logfile.txt &
app --logfile logfifo

당신하면 어떻게됩니까 cat logfifo프로세스 다이, 누군가가 사고를 죽이고, 또는 누군가가 실수로 잘못된 위치에 포인트?

내 경험은 app의지가 빨리 막히고 멈추는 것입니다. Tomcat, Apache 및 몇 가지 작은 자체 빌드 응용 프로그램 으로이 작업을 시도했지만 동일한 문제가 발생했습니다. logger간단한 I / O 리디렉션이 원하는 것을 수행 했기 때문에 나는 결코 멀리 조사 하지 않았습니다. 나는 보통 로깅 완성도가 필요하지 않습니다. 이것은 당신이 추구하는 것입니다. 그리고 당신이 말하는 것처럼, 당신은 로거를 원하지 않습니다.

Linux 비 차단 fifo (온 디맨드 로깅) 에서이 문제에 대한 논의가 있습니다 .


흥미 롭군 그래도 앱이 차단 될 수 있습니까? 우리는 지금 수건을 던지고 Fusion IO를 주문할 생각입니다.
chrisaycock

시도 해봐. 저 에게이 결과는 사양이 낮은 하드웨어의 테스트 환경에서 빠르게 발생했습니다. 이것은 Ubuntu와 RedHat 5에 있습니다. FreeBSD 등이 비슷한 동작을하는지 확실하지 않습니다.
Stefan Lasiewski 1

2

옵션은 앱에 의해 상당히 제한적이지만 테스트 한 기능이 작동합니다.

우리는 유용한 로그를 얻기 위해 varnish 및 varnishncsa와 비슷한 것을 수행합니다. 우리는 fifo를 가지고 있으며 syslog-ng로 그것을 읽고 필요한 곳에 보냅니다. 우리는 약 50GB를 처리하고 지금 까지이 방법으로 문제를 겪지 않았습니다.


시원하고 기쁜 소식은 우리가 이것 만 생각 해낸 사람이 아니라는 점입니다.
chrisaycock

2

환경은 CentOS이며 응용 프로그램은 파일에 씁니다 ...

일반 파일로 보내는 대신 출력을 syslog로 보내고 syslog 메시지가 로컬 서버뿐만 아니라 중앙 서버로 보내지고 있는지 확인합니다.

다음과 같은 쉘 스크립트를 사용할 수 있어야합니다.

logger -p daemon.notice -t app < fifo

파이프 logger에서 cat또는 tail -f파이프로 입력을받을 수도 있습니다 .

tail -f fifo | logger ...
cat fifo | logger ...

유일한 문제는 로그 메시지의 중요성 (모든 것이 NOTICE )에 따라 구분되지 않지만 최소한 로그되어 호스트 외부로 중앙 서버로 전송된다는 것입니다.

syslog 구성은 사용중인 서버에 따라 다릅니다. 이 rsyslogsyslog-ng(모두 매우 가능).

편집 : 포스터에서 더 많은 정보를 얻은 후 수정되었습니다.


로그 메시지는 선택할 수있는 파일에 기록되지만 응용 프로그램은에 기록하지 않습니다 stdout. OS는 CentOS입니다 (질문을 linux 로 태그 지정 했지만 쉽게 놓칠 수 있습니다). 모든 메시지의 중요성은 동일하므로이 응용 프로그램의 통지와 오류간에 차이가 없습니다.
chrisaycock

통지와 오류의 차이가 없습니까? 아 진짜 ? 간의 차이 없음 Slow query detectedDatabase halted?
Mei

(나는 게시물을 업데이트했습니다.)
Mei

1

당신은 쓰기:

또한 응용 프로그램에 쓰지 않습니다 stdout...

"파일"에 로깅을 시도 했습니까 /dev/stdout? 그러면 다음과 같은 작업을 수행 할 수 있습니다.

app --logfile /dev/stdout | logger -t app

FIFO와 다른가요? 문제는 무엇입니까? 나는 대안을 찾고 있지 않다 자체 ; 내가 나열한 접근 방식이 강력한 지에 대한 통찰을 찾고 있습니다. 그게 내가 관심있는 전부 야.
chrisaycock

1
예, FIFO와 다릅니다. 기본적으로 STDOUT에 연결된 파일입니다. 이를 사용하여 STDOUT에 로그하고 syslog 또는 이와 유사한 로그에 사용할 수 있습니다. 원래 문제에 대한 해결책으로 고안되었지만 움직이는 부품 수가 적어 FIFO보다 강력합니다.
nickgrim

1

fifo에 기록한 다음 다른 프로세스가 파일에 기록하도록 할 필요는 없습니다. 정상적으로 파일에 직접 쓰면 일단 write()리턴되면 커널의 손에 달려 있습니다. 응용 프로그램이 충돌해도 여전히 디스크에 기록합니다.


모든 로그 메시지가 플러시됩니다 . 쓰기가 차단됩니다. 우리는 애플리케이션의 소스 코드를 가지고 있지 않기 때문에 제어 할 수 없습니다.
chrisaycock

@ chrisaycock, 맞아 ... 그래서 문제는 어디에 있습니까?
psusi

동료들과 저는 로그 메시지가 프로세스를 벗어나도록 보장하면서 버퍼링의 성능 효과를 얻는 방법에 대해 궁금했습니다.
chrisaycock

@ chrisaycock, 오, 응용 프로그램은 현재 O_SYNC를 사용하거나 fsync()각 쓰기가 디스크에 도달 할 때까지 기다릴 때 발생하지 않기를 원합니다 (시스템 충돌시 손실 위험)?
psusi

1
@ chrisaycock, 그것은 드라이브의 인터페이스와 관련이 없습니다. 일반적으로 커널이 파일 시스템 캐시 (및 응용 프로그램 외부)에 커널을 복사했음을 의미합니다. 원래 대답에서 말했듯이 일단 write()앱이 반환되면 앱이 좋아하는 모든 것을 중단 할 수 있습니다. 커널이 충돌하지 않는 한 데이터는 디스크에 저장됩니다.
psusi
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.