UNIX 命名 PIPE 文件结尾
我正在尝试使用 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
它在大多数情况下都运行良好。但是,如果我连续快速多次搜索该条目,有时我会得到多行一些有趣的统计信息
,而不是一行。有一两次,它甚至进入了无限循环,永远打印该行,直到我杀死它。到目前为止,我得到的唯一修复是在 f.close()
之后延迟 500 毫秒,以防止出现此问题。
我想知道为什么会发生这种情况以及是否有更好的方法来处理它。
提前致谢
I'm trying to use a unix named pipe to output statistics of a running service. I intend to provide a similar interface as /proc
where one can see live stats by catting a file.
I'm using a code similar to this in my python code:
while True:
f = open('/tmp/readstatshere', 'w')
f.write('some interesting stats\n')
f.close()
/tmp/readstatshere
is a named pipe created by mknod
.
I then cat it to see the stats:
$ cat /tmp/readstatshere
some interesting stats
It works fine most of the time. However, if I cat the entry several times in quick successions, sometimes I get multiple lines of some interesting stats
instead of one. Once or twice, it has even gone into an infinite loop printing that line forever until I killed it. The only fix that I've got so far is to put a delay of let's say 500ms after f.close()
to prevent this issue.
I'd like to know why exactly this happens and if there is a better way of dealing with it.
Thanks in advance
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
在这里,管道根本就是错误的解决方案。如果您想提供进程内部状态的一致快照,请将其写入临时文件,然后将其重命名为“公共”名称。这将防止在您更新状态时其他进程读取状态可能引起的所有问题。另外,不要在繁忙的循环中执行此操作,但最好在更新之间睡眠至少一秒的线程中执行此操作。
A pipe is simply the wrong solution here. If you want to present a consistent snapshot of the internal state of your process, write that to a temporary file and then rename it to the "public" name. This will prevent all issues that can arise from other processes reading the state while you're updating it. Also, do NOT do that in a busy loop, but ideally in a thread that sleeps for at least one second between updates.
用 UNIX 套接字代替管道怎么样?
在这种情况下,您可以通过及时提供新数据来对每个连接做出反应。
唯一的缺点是您无法
cat
数据;您必须创建一个新的套接字句柄并使用connect()
连接到套接字文件。查询该套接字的程序:
What about a UNIX socket instead of a pipe?
In this case, you can react on each connect by providing fresh data just in time.
The only downside is that you cannot
cat
the data; you'll have to create a new socket handle andconnect()
to the socket file.Program querying this socket:
我认为你应该使用保险丝。
它有 python 绑定,请参阅 http://pypi.python.org/pypi/fuse-python/
这使您可以回答以 posix 文件系统系统调用形式表述的问题
I think you should use fuse.
it has python bindings, see http://pypi.python.org/pypi/fuse-python/
this allows you to compose answers to questions formulated as posix filesystem system calls
不要写入实际文件。这不是
/proc
所做的。 Procfs 提供了一个虚拟(非磁盘支持)文件系统,它可以按需生成您想要的信息。您可以做同样的事情,但如果它不与文件系统绑定,它会更容易。相反,只需在 Python 程序中运行 Web 服务,并将统计信息保存在内存中。当收到统计数据请求时,将它们格式化为一个漂亮的字符串并返回它们。大多数时候,您不需要浪费周期来更新文件,该文件甚至可能在下次更新之前不会被读取。Don't write to an actual file. That's not what
/proc
does. Procfs presents a virtual (non-disk-backed) filesystem which produces the information you want on demand. You can do the same thing, but it'll be easier if it's not tied to the filesystem. Instead, just run a web service inside your Python program, and keep your statistics in memory. When a request comes in for the stats, formulate them into a nice string and return them. Most of the time you won't need to waste cycles updating a file which may not even be read before the next update.在发出
close
后,您需要取消
管道的链接。我认为这是因为存在竞争条件,在cat
完成之前可以再次打开管道进行读取,因此它会看到更多数据并将其读出,从而导致“一些有趣的统计数据”的倍数。基本上你想要类似的东西:
更新 1:调用
mkfifo
更新 2:如注释中所述,此代码中存在竞争条件以及多个消费者。
You need to
unlink
the pipe after you issue theclose
. I think this is because there is a race condition where the pipe can be opened for reading again beforecat
finishes and it thus sees more data and reads it out, leading to multiples of "some interesting stats."Basically you want something like:
Update 1: call to
mkfifo
Update 2: as noted in the comments, there is a race condition in this code as well with multiple consumers.