2011-09-24 90 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