PHP Inotify非阻塞方式

我正在读取一个文件在Linux是一个日志文件,不断更新天气文件已经改变,并输出到网页。 我这样做使用PHP inotify但我的问题是,它阻止。

我如何使php inotify非阻塞,所以我可以做其他的东西,而它是监测文本文件?

<?php $fd = inotify_init(); $watch_descriptor = inotify_add_watch($fd, '/tmp/temp.txt', IN_MODIFY); touch('/tmp/temp.txt'); $events = inotify_read($fd); $contents = file_get_contents('/tmp/temp.txt'); echo $contents; inotify_rm_watch($fd, $watch_descriptor); fclose($fd) ?> 

或者我可以在java中做到这一点?..谢谢。

是的你可以。 你看过手册吗? 它提供了非阻塞事件回调的例子? 如果此答案没有充分回答您,请添加更多信息。

http://php.net/manual/en/function.inotify-init.php

 // Open an inotify instance $fd = inotify_init(); // - Using stream_set_blocking() on $fd stream_set_blocking($fd, 0); // Watch __FILE__ for metadata changes (eg mtime) $watch_descriptor = inotify_add_watch($fd, __FILE__, IN_ATTRIB); // generate an event touch(__FILE__); // this is a loop while(true){ $events = inotify_read($fd); // Does no block, and return false if no events are pending // do other stuff here, break when you want... } // Stop watching __FILE__ for metadata changes inotify_rm_watch($fd, $watch_descriptor); // Close the inotify instance // This may have closed all watches if this was not already done fclose($fd); 

这就像Layke说的。 你可以让它阻塞或不阻塞。 如果它是非阻塞的,你必须进行轮询。 我想你想要的是以多线程方式阻止。 一个线程工作在阻塞或非阻塞,频繁的轮询模式,而另一个线程做别的事情。

我建议通过使用node.js.这件事情会容易得多node.js.

你只需要下面的代码:(文件名:watch.js)

  var fs = require('fs'); var file = '/tmp/temp.txt/'; fs.watchFile(file, function (curr, prev) { console.log('the current mtime is: ' + curr.mtime); console.log('the previous mtime was: ' + prev.mtime); }); 

那么你可以运行它:

  node watch.js 

它将持续运行。

使用javascript编写server-side程序的node.js ,它具有non-blocking I/O模型。 它可以帮助你轻松地做这种事情。

这里是一些相关的文件fs.watchFile

我喜欢这样的东西会使用Java,因为我觉得更容易管理后台任务,如你所描述的。

后端

我的方法是使用Java EE创建一个实现调度程序服务的单例启动线程。 使用单例启动线程的原因是,您的工作可以作为后台进程运行,因此是非阻塞的,为应用程序的其余部分释放资源。 而且线程可以通过调用类的方法来访问。 您可以安排任务,每n秒钟/分钟等读取您的文件等任何更新,然后这些可以提供给您的前端。

基本示例:

 @Singleton @Startup public class Scheduler { private static int count = 0; private Weather weather; public Weather getWeather() { return weather; } @PostConstruct public void onStartup() { System.out.println("Initialization success."); } @Schedule(second="*/10", minute="*", hour="*") public void execute() { byte[] encoded = Files.readAllBytes(Paths.get("weather_updates.txt")); String weatherUpdateStr = encoding.decode(ByteBuffer.wrap(encoded)).toString(); weather = new Weather(); weather.parse(weatherUpdateStr); // Possible addition of logic for push to web socket } } 

这个基本的例子创建一个sigleton线程作为你的web应用程序容器(我推荐使用JBoss 7)启动。 然后创建一个每10秒执行一次的计划任务。 提供的代码执行一个基本的Java 7文件读取到一个字符串和weather.parse()应该包含一些逻辑将字符串转换为Weather对象。 天气对象然后准备好通过网络套接字推送或通过前端的一些AJAX请求轮询。

前端

我会在这里建议两种可能的方法:

  1. 使用HTML5的网络套接字
  2. AJAX调用

1.网络套接字

Web套接字被引入到HTML5中,作为在页面上提供动态内容的一种方式,而不需要刷新或使用AJAX调用。 这里是HTML5中的websockets的一个很好的介绍。 这是另一个如何用Java设置HTML5 websockets的很好的例子 。

2. AJAX调用

jQuery为AJAX提供了一个很好的API。 您可以在jQuery中实现Timeout任务,该任务将间歇性地执行一些功能。 您将要实现的功能是和AJAX获取请求 。

基本示例:

 $.ajax({ url: "getWeatherUpdate.html", error: function(){ // will fire when timeout is reached }, success: function(){ // Update your webpage with weather info }, timeout: 3000 // sets timeout to 3 seconds }); 

您可以看看React库,它基于反应堆模式在PHP中提供事件驱动的非阻塞I / O Api: http : //reactphp.org/