2011-09-24 58 views
3

我正在嘗試使用unix命名管道來輸出正在運行的服務的統計信息。我打算提供一個類似於/proc的界面,其中可以通過捕獲文件來查看實時統計信息。UNIX名爲PIPE文件結尾

我用我的Python代碼類似下面的代碼:

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

/tmp/readstatsheremknod創建命名管道。

我然後貓就看到統計:

$ cat /tmp/readstatshere 
some interesting stats 

它正常工作的大部分時間。但是,如果我連續多次登錄該條目,有時會得到多行some interesting stats而不是一條。一次或兩次,它甚至進入無限循環打印該行,直到我殺死它。到目前爲止,我唯一的解決方法是在f.close()之後延遲500毫秒以避免此問題。

我想知道爲什麼發生這種情況,如果有更好的方式處理它。

在此先感謝

+0

有沒有理由使用命名管道與普通文件? –

+0

@Mansour合併完成。 –

回答

1

一個管道就是這裏錯誤的解決方案。如果你想呈現一個一致的快照你的進程的內部狀態,將其寫入臨時文件,然後將其重命名爲「公共」名稱。這將防止其他進程在更新時讀取狀態時可能出現的所有問題。另外,不要在繁忙的循環中執行該操作,但理想情況下是在更新之間至少休眠一秒的線程。

+0

好吧,由於Linux緩衝區緩存的一些死鎖問題,我實際上無法做任何會導致在緩存中創建髒頁的任何事情。這就是我選擇管道的原因。 – Mansour

0

請勿寫入實際文件。這不是/proc。 Procfs提供了一個虛擬(非磁盤備份)文件系統,可以根據需要生成您想要的信息。你可以做同樣的事情,但如果它不依賴於文件系統,它會更容易。相反,只需在Python程序中運行Web服務,並將統計信息保存在內存中。當請求進入統計數據時,將它們製作成一個漂亮的字符串並返回它們。大多數情況下,您不需要浪費週期來更新文件,在下次更新之前甚至可能無法讀取這些文件。

+0

嗯,從我的理解和測試到目前爲止,Python代碼塊在'open'直到另一個進程打開管道閱讀 - 這種行爲,它會_look like_'/proc'。問題是,'open'有時不會阻塞,導致多個統計輸出。創建一個普通的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

好的,但是如果讀者試圖打開管道,'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

我認爲你應該使用的保險絲。 它有python綁定,看到http://pypi.python.org/pypi/fuse-python/ 這允許您撰寫的答案配製成POSIX文件系統的系統調用的問題

+0

這個解決方案看起來像是一種矯枉過正。 – Mansour