2011-09-24 5 views
3

실행중인 서비스의 통계를 출력하기 위해 유닉스 명명 된 파이프를 사용하려고합니다. 나는 /proc과 유사한 인터페이스를 제공하고자합니다. 파일을 catting하여 실시간 통계를 볼 수 있습니다.UNIX라는 이름의 파일 끝 파일

나는 내 파이썬 코드에서 다음과 유사한 코드를 사용하고 있습니다 :

while True: 
    f = open('/tmp/readstatshere', 'w') 
    f.write('some interesting stats\n') 
    f.close() 

/tmp/readstatsheremknod 만든 명명 된 파이프입니다.

나는 그 고양이는 통계를 볼 수 있습니다 : 그것은 대부분의 시간을 잘 작동

$ cat /tmp/readstatshere 
some interesting stats 

. 그러나, 나가 빠른 연속 안에 입장을 몇 시간 붙잡는 경우에, 때때로 나는 1 대신에 some interesting stats의 다수 선을 얻는다. 한 두 번, 내가 그것을 죽일 때까지 그 줄을 영원히 인쇄하는 무한 루프에도 들어갔다. 지금까지 얻은 유일한 해결책은이 문제를 방지하기 위해 f.close() 이후에 500ms를 지연시키는 것입니다.

왜 이런 일이 발생했는지, 그리고 더 좋은 방법이 있는지 알고 싶습니다.

미리 감사드립니다.

+0

일반 파일과 일반 파일을 사용해야하는 이유가 있습니까? –

+0

@Manour Merge가 완료되었습니다. –

답변

1

파이프가 단순히 잘못된 해결책 일뿐입니다. 프로세스의 내부 상태에 대한 일관된 스냅 샷을 표시하려면 임시 파일에 기록한 다음 "공개"이름으로 바꿉니다. 이렇게하면 업데이트하는 동안 다른 프로세스가 상태를 읽음으로써 발생할 수있는 모든 문제를 방지 할 수 있습니다. 또한 바쁜 루프에서 그러지 마라. 이상적으로는 업데이트 사이에 최소한 1 초 동안 잠자는 스레드에있는 것이 이상적이다.

+0

글쎄, 리눅스 버퍼 캐시에 관한 교착 상태 문제로 인해 캐시에 더티 페이지를 생성하는 것은 실제로 할 수 없습니다. 그래서 내가 파이프를 선택했습니다. – Mansour

0

실제 파일에 쓰지 마십시오. 그건 /proc이하는 것이 아닙니다. Procfs는 필요에 따라 원하는 정보를 생성하는 가상 (디스크가 아닌) 파일 시스템을 제공합니다. 똑같은 일을 할 수 있지만, 파일 시스템에 묶여 있지 않다면 더 쉬울 것입니다. 대신 Python 프로그램에서 웹 서비스를 실행하고 통계를 메모리에 보관하십시오. 요청에 대한 통계가 들어 오면 좋은 문자열로 공식화하여 반환하십시오. 대부분의 경우 다음 업데이트 전에 읽지 않을 수도있는 파일을 업데이트하는 데 낭비 할 필요가 없습니다.

+0

흠, 내 이해와 테스트에서, 다른 프로세스가 읽기 위해 파이프를 열 때까지 파이썬 코드 블록이'open'으로 블록됩니다 -이 동작으로,'like /'proc'를 볼 수 있습니다. 문제는 '열린'이 때때로 차단되지 않고 여러 통계가 출력되는 것입니다. 정상적인 TCP 소켓을 만드는 것이 첫 번째 선택 이었지만 통계를 읽는 또 다른 작은 프로그램을 의미했습니다. 나는 물건을 간단하고 최소한으로 유지하기를 원했습니다. – Mansour

+3

@Mansour가 실제 파일에 쓰지 않습니다. 그는 명명 된 파이프를 사용하고 있습니다. 'write' 호출은 리더가 준비 될 때까지 차단 될 것입니다 - 순환을 낭비하지 않을 것입니다. – dowski

0

close을 발급 한 후 unlink 파이프가 필요합니다. 이것은 파이프가 cat이 끝나기 전에 다시 읽을 수있는 경쟁 조건이 있기 때문에 더 많은 데이터를보고 그것을 읽음으로써 "흥미로운 통계"의 배수가되기 때문입니다.

while True: 
    os.mkfifo(the_pipe) 
    f = open(the_pipe, 'w') 
    f.write('some interesting stats') 
    f.close() 
    os.unlink(the_pipe) 

업데이트 1 : mkfifo

업데이트 2로 전화 :

은 기본적으로 당신은 같은 것을 원하는 의견에 언급 한 바와 같이,이 코드에서 경쟁 조건으로뿐만 아니라이 여러 소비자.

+0

파이프를 연결 해제하지 않았습니까? 누가 다시 그것을 다시 만들 것입니까? – Mansour

+0

Woops, 좋은 지적입니다. 내 예제에서'mkfifo'에 대한 호출을 놓쳤습니다. 나는 그것을 새롭게 할 것이다. – dowski

+0

OK,하지만 독자가 파이프를 열려고하면'os.unlink'와'os.mkfifo' 사이에는 경쟁 조건이 있습니다. – Mansour

1

파이프 대신 UNIX 소켓이 필요합니까?

이 경우, 새로운 데이터를 제 시간에 제공하여 각 연결에 대응할 수 있습니다.

유일한 단점은 사용자가 cat 데이터를 사용할 수 없다는 것입니다. 새 소켓 핸들을 만들고 소켓 파일에 connect()을 만들어야합니다. 이 소켓을 조회

MYSOCKETFILE = '/tmp/mysocket' 
import socket 
import os 
try: 
    os.unlink(MYSOCKETFILE) 
except OSError: pass 
s = socket.socket(socket.AF_UNIX) 
s.bind(MYSOCKETFILE) 
s.listen(10) 
while True: 
    s2, peeraddr = s.accept() 
    s2.send('These are my actual data') 
    s2.close() 

프로그램 :

MYSOCKETFILE = '/tmp/mysocket' 
import socket 
import os 
s = socket.socket(socket.AF_UNIX) 
s.connect(MYSOCKETFILE) 
while True: 
    d = s.recv(100) 
    if not d: break 
    print d 
s.close() 
+0

예, 먼저 그것을 고려했지만 소켓 (내 경우에는 TCP)과 대화하기 위해 별도의 프로그램을 작성하는 것을 피하려고했습니다. – Mansour

1

난 당신이 퓨즈를 사용한다고 생각합니다. 파이썬 바인딩이 있습니다. http://pypi.python.org/pypi/fuse-python/을 참조하십시오. 이것은 posix 파일 시스템 시스템 호출로 공식화 된 질문에 대한 답변을 구성 할 수 있습니다.

+0

이 솔루션은 과도한 것처럼 보입니다. – Mansour

관련 문제