我正在读取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中执行此操作吗?..谢谢。
答案 0 :(得分:4)
是的,你可以。你看过手册了吗?它提供了非阻塞事件回调示例?如果此答案没有充分回答您,请添加更多信息。
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 (e.g. 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);
答案 1 :(得分:2)
就像Layke说的那样。您可以阻止或阻止它。如果它是非阻塞的,你必须进行轮询。我想你想要的是多线程阻塞。一个线程用于阻塞或非阻塞,频繁轮询,模式,而另一个线程则执行其他操作。
答案 2 :(得分:1)
我建议使用node.js.
您只需要以下代码:(filename: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
它将持续运行。
node.js
使用javascript编写server-side
程序,它有non-blocking I/O
模型。它可以帮助你轻松做到这一点。
以下是一些相关文档fs.watchFile
答案 3 :(得分:1)
我喜欢这样的事情就是使用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对象的逻辑。然后,天气对象可以通过Web套接字推送,也可以通过前端的某些AJAX请求进行轮询。
<强>前端强>
我建议有两种可能的方法:
<强> 1。网络插座
Web套接字被引入到HTML5中,作为在页面上提供动态内容的一种方式,无需刷新或使用AJAX调用。 Here是对HTML5中的websockets的一个很好的引用。 Here is another great example of how to set up HTML5 websockets with Java
<强> 2。 AJAX调用
jQuery为AJAX提供了一个很棒的API。您可以在jQuery中实现一个Timeout任务,它将间歇性地执行某些功能。您要实现的功能是AJAX Get request。
基本示例:
$.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
});
答案 4 :(得分:1)
您可以查看React库,它基于reactor模式在PHP中提供事件驱动的非阻塞I / O Api: http://reactphp.org/