2015-08-14 186 views
1

我有一個'服務器'進程產生一些日誌。我希望用戶(或其他服務)能夠查看該日誌流(如tail -f),但我不想將這些日誌寫入文件系統。我可以在Linux上執行此操作嗎?Linux上的一對多進程間通信

  1. 我的第一次嘗試是在回送接口上使用UDP。服務器將數據包發送到端口12345上的localhost,客戶端可以綁定到該端口以接收它們。不起作用。因爲只有一個客戶端可以綁定到同一個套接字。啊!但是你可能會說使用SO_REUSE_ADDR,它允許兩個客戶端綁定到一個端口,但只有一個客戶端接收到這些消息。

  2. 接下來,我嘗試在回送接口上的UDP多播。那個沒有得到,因爲我的內核不支持在回送接口上的多播。據ifconfig

    lo  Link encap:Local Loopback 
          inet addr:127.0.0.1 Mask:255.0.0.0 
          UP LOOPBACK RUNNING MTU:65536 Metric:1 
          RX packets:186 errors:0 dropped:0 overruns:0 frame:0 
          TX packets:186 errors:0 dropped:0 overruns:0 carrier:0 
          collisions:0 txqueuelen:0 
          RX bytes:11904 (11.6 KiB) TX bytes:11904 (11.6 KiB) 
    

    注缺乏MULTICAST(或BROADCAST,確實),上面。

有沒有人有任何想法?我可以使用命名管道或Unix域套接字來解決這個問題嗎?

我想避免任何允許(無特權)偵聽器影響(特權)服務器的內容。例如,我寧願刪除日誌而不是阻止服務器。

我在Python中完成所有這些工作,如果這樣做有任何區別的話。

+0

在您的第一段中提出了一個問題:如果只能實時閱讀,那麼記錄的用法是什麼?什麼不把它放在一個文件中? – HuStmpHrrr

+0

它基本上需要運行連接到客戶端的輪詢循環('select','poll','epoll'),維護活動客戶端列表,並在生成後立即發送最新日誌。可能最好使用pipe通過管道將日誌從主服務器傳遞給helper tcp/udp服務器,然後在那裏執行循環。 – HuStmpHrrr

回答

1

你可以看看ZeroMQ。你所描述的是一種對發佈者/訂閱者模式的需求,這正是ZeroMQ確實非常優雅的事情。它具有額外的優勢,即在下面使用什麼類型的交通工具時非常靈活; IPC,TCP等。這使得將程序中的其他部分放在網絡上非常簡單。使用ZeroMQ,您將得到非常簡單的源代碼,所有這些複雜性都隱藏在zmq庫中。你可以先看看guide

這部分你也可以考慮NanoMSG(即將到來的ZeroMQ-done-better),儘管我不確定它還有Python綁定。

+0

這看起來很不錯。我一直錯誤地認爲ZeroMQ使用經紀人流程!而PUB套接字類型不會阻塞。我會進一步調查... – joerick

+0

@joerick,是的,無經紀人是好的。爲了記錄,數據分發服務也是無代理的。 RabbitMQ有一個經紀人,人們不知道什麼時候休息。在ZeroMQ中,後臺運行的線程完成所有工作,但最終的結果是它們都不是整個系統運行的關鍵。一個人休息,其他一切都繼續,希望。重新啓動破碎的,一切正常進行。 – bazza

1

我可以想到兩種通用方法。

1)使用POSIX共享內存對象。

有關更多信息,請參見shm_open(3)手冊頁。

您的應用程序將創建一個共享內存對象,它將在其中寫入其日誌消息,並且任何客戶端應用程序都可以打開共享內存對象並讀取它。儘管POSIX共享內存API看起來像基於文件系統的API,但事實並非如此。

現在請記住,您將獲得一大塊您需要的大小的內存。您必須弄清楚您的應用程序將如何構建,並以一種有意義的方式管理您的客戶端應用程序可以解析的這部分內存,並輪詢更改的內容。

2)

您的應用程序帶有打開並監聽本地主機插座,或文件系統域套接字的負擔,任何客戶端可以連接到,你的應用程序將簡單地寫了日誌消息到每一個客戶端連接目前存在。

這是有點棘手得到正確的。您的應用程序需要能夠不斷接受來自客戶端的新連接,無論何時它們進入,將消息寫入所有併發連接,檢測某個客戶端何時卡住,是否從套接字末尾讀取,從而使本地套接字處於內部緩衝區已滿,因此阻塞寫入會阻止並掛起主應用程序;因此所有寫入必須是非阻塞權利,並且應用程序會自動關閉任何變滿的插槽等等...等等......