我正在读取一个文件在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.网络套接字
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/