我正在尝试使用unix命名管道输出正在运行的服务的统计信息。我打算提供一个与/proc
类似的界面,通过捕捉文件可以看到实时统计数据。
我在我的python代码中使用了与此类似的代码:
while True:
f = open('/tmp/readstatshere', 'w')
f.write('some interesting stats\n')
f.close()
/tmp/readstatshere
是由mknod
创建的命名管道。
然后我试着看看统计数据:
$ cat /tmp/readstatshere
some interesting stats
大部分时间都可以正常工作。但是,如果我快速连续几次捕获该条目,有时我会得到多行some interesting stats
而不是一行。有一次或两次,它甚至进入无限循环打印那条线直到我杀了它。到目前为止,我唯一能解决的问题是在f.close()
之后延迟500分钟以防止此问题。
我想知道为什么会发生这种情况,以及是否有更好的方法来处理它。
提前致谢
答案 0 :(得分:1)
管道在这里只是错误的解决方案。如果要显示进程内部状态的一致快照,请将其写入临时文件,然后将其重命名为“public”名称。这将防止在您更新状态时读取状态的其他进程可能出现的所有问题。另外,请勿在繁忙的循环中执行此操作,但最好不要在更新之间至少休息一秒的线程中执行此操作。
答案 1 :(得分: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()
答案 2 :(得分:1)
我认为你应该使用保险丝。 它有python绑定,请参阅http://pypi.python.org/pypi/fuse-python/ 这允许您撰写对posix文件系统系统调用的问题的答案
答案 3 :(得分:0)
不要写入实际文件。这不是/proc
所做的。 Procfs提供了一个虚拟(非磁盘支持)文件系统,可根据需要生成您想要的信息。你可以做同样的事情,但如果它不依赖于文件系统,它会更容易。相反,只需在Python程序中运行Web服务,并将统计信息保存在内存中。当请求进入统计数据时,将它们表示为一个很好的字符串并返回它们。大多数情况下,您不需要浪费周期更新文件,这些文件在下次更新之前甚至无法读取。
答案 4 :(得分:0)
发出unlink
后,您需要close
管道。我认为这是因为存在一种竞争条件,即管道可以在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:如评论中所述,此代码中存在竞争条件以及多个消费者。