处理包装程序输出的包装守护程序
我有一个小爱好项目,我正在 Linux 中用 C 语言编写一个“包装器”守护进程。也就是说,它的目的是启动、监视、向其他程序发出命令和停止其他程序。该守护进程还提供一个 Web 界面,用户可以在其中登录并操作正在运行的程序。
现在的设置方式是,每当程序写入其标准输出时,该输出都会重定向到管道。每当有人通过 Web 界面访问该程序时,Web 界面就会开始通过 XMLHttpRequest() 轮询守护进程,然后守护进程会检查是否已将某些内容写入管道并发送回响应,其中包含管道中的内容时间。
主要问题是当我有两个(或更多)用户登录并尝试与同一个程序交互时。由于 Web 界面有效地轮询管道中是否有任何写入内容,因此每当多个用户登录并监视同一程序时,该程序的输出就会随机发送给其中一个用户。这显然是不好的。
我目前正在考虑解决这个问题的一个解决方案是对程序生成的所有输出添加时间戳,并将这些信息存储在数据库之类的东西中。当 Web 界面使用时间戳轮询守护进程时,守护进程只需收集此后写入的所有输出并将其发回。
我认为类似上述解决方案可以解决多用户问题,但我想我应该尝试一下并向 Stack Overflow 社区询问这个问题。对于这样的问题有更好的解决方案吗? (鉴于我已经设法以一种可以理解的方式描述问题)。
I have a small hobby project where I'm writing a 'wrapper'-daemon in linux, in C. That is, it's purpose is to start, monitor, issue commands to and stop other programs. The daemon also serves up a web interface where users can log in and manipulate the running programs(s).
The way it's set up right now is that whenever a program writes to its stdout, this output is redirected to a pipe. Whenever someone then accesses the program through the web interface, the web interface starts polling the daemon through XMLHttpRequest()'s, the daemon then checks if something has been written to the pipe and sends back a response with whatever was in the pipe at the time.
The main issue is when I have two (or more) users logged in and trying to interact with the same program. Since the web interface effectively polls the pipe for anything written, whenever several users are logged in and monitoring the same program, the output of that program is randomely sent to one of the users. This is obviously bad.
The one solution to solving this that I'm contemplating at the moment is to timestamp all output that a program generates and store this information in something like a database. When the web interface then polls the daemon with a timestamp, the daemon simply collects all the output that has been written since and sends this back.
I think something like the above solution would solve the multi-user issue but I thought I would take a stab and query the Stack Overflow community about this problem. Is there some better solution to a problem like this? (Given I've managed to describe the problem in a somewhat understandable way that is).
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
除非您希望所有返回的用户在下次登录时都能看到每个给定程序的所有输出,否则我认为没有必要将信息存储在数据库中。这听起来也有点贵。
您需要的是某种会话实现和标记化系统,用户可以在其中“订阅”某些输出流。当
select()
或poll()
在管道 fd 上触发时,该数据应写入该特定进程的所有订阅者。您可以同时实现这两种方法,其中未到达订阅用户的数据将被存储,以便在他们下次登录时显示。这不一定是一个复杂的甚至是 SQL 数据库,一个简单的键 =>值对的工作原理如下(例如,仅将其存储在 INI 文件中:
我最初对您的问题感到困惑,但再次阅读后,我意识到我们正在开发几乎相同的项目。我的是将一个简单的串行客户端附加到伪 TTY它提供与 Ajaxterm 非常相似的功能,它有助于访问半虚拟化 Xen 虚拟机的控制台。
Unless you want all returning users to be presented with all of the output from every given program on their next login, I don't think that storing the information in a database is necessary. That also sounds like it would be a bit on the expensive side.
What you need is some kind of session implementation and tokenization system where users 'subscribe' to certain output streams. When
select()
orpoll()
fires on the pipe fd, that data should be written to all subscribers of that particular process.You could implement both, where data that did not reach a subscribed user would be stored for displaying upon their next login. That need not be a complex or even SQL database, a simple key => value pair would work like (example just storing it in an INI file:
I was initially confused with your question, but after reading it again I realized that we are working on nearly identical projects. Mine is attaching a simple serial client to a psuedo TTY which feeds something very similar to Ajaxterm. It facilitates access to consoles to paravirtualized Xen virtual machines.
抽象地说,你有一种分叉的队列。主机上的程序产生的输出在头部排队,用户各自从自己的尾部消费。 “消费”部分有点有趣,因为您不想“忘记”内容,直到所有感兴趣的用户都看到它。 Tim Post 建议每个用户流使用一个简单的队列,生产者排队到所有“订阅”队列中。另一种方法是每个生产者队列,用光标标记用户已经看到的距离。后一种方法比较简洁,因为它不会复制任何内容,但确实会迫使您弄清楚每个人何时都看到了尾随内容,以便您可以忘记它。
我想我会尝试后一种方法,并把赌注押在遗忘上。也就是说,永远存储所有输出。这对用户来说也可能很有吸引力 - 毕竟,哪个终端仿真器没有大容量的向后滚动缓冲区?它是更多的存储空间,但现在存储空间便宜得令人尴尬。
我不认为使用数据库一定是一个坏主意。例如,您可能希望在生成输出时将时间戳与输出相关联,或者在内容中执行搜索。跟踪用户在流中看到的距离很可能由 rowid 完成,但用户可能会喜欢“显示过去一小时的输出”类型的界面。将每个队列存储为一个表,其中行按时间索引将是数据库的自然工作负载,在空间和时间上非常高效。但是基本的不忘记队列可以非常简单地作为每个流的文件来完成,并将用户位置存储为偏移量。
Tim 的方法采用每用户流,在生产者的上下文中做了更多的工作,具体取决于生产者拥有多个订阅者的频率。如果你的生产者像 Twitter 一样,这不是一个可行的方法:被数百万用户观看;)但是他的每用户流方法也不会打扰垃圾收集,还可以包括数据库和时间戳的想法。
in abstract, you have a sort of queue that forks. programs on the host produce output that gets enqueued at the head and users each consume from their own tail. the "consume" part is a little funny, because you don't want to "forget" content until all interested users have seen it. Tim Post suggests using a simple queue per user-stream, with the producer enqueueing to all "subscribed" queues. The other approach is a queue-per-producer, with a cursor to mark how far a user has already seen. The latter approach is parsimonious in that it doesn't replicate anything, but does force you to figure out when everyone has seen trailing content so you can forget it.
I think I'd try the latter approach, and just punt on forgetting. that is, always store all output forever. this is potentially quite attractive to users, as well - after all, what terminal emulator doesn't have a generous-sized scroll-back buffer? it's more storage, but storage is embarassingly cheap these days.
I don't think using a DB is necessarily a bad idea. you might, for instance, want to associate a timestamp with output as it is produced, or to perform searches within the content. tracking how far in a stream users have seen would most likely be done by rowid, but users might appreciate a "show me output for the last hour" kind of interface. storing each queue as a table, with rows indexed by time would be a natural workload for a DB, pretty efficient in space and time. but the basic no-forget queue could be done very simply as a file-per-stream with user positions stored as offset.
Tim's approach, with per-user streams, does a bit more work in the producer's context, depending on how often a producer has multiple subscribers. not a viable approach if your producers are like twitter: being watched by millions of users ;) but his stream-per-user approach could also not bother garbage-collecting, could also include the DB and timestamp ideas.