PHP Inotify非阻塞方式

时间:2012-10-29 14:17:14

标签: php linux

我正在读取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中执行此操作吗?..谢谢。

5 个答案:

答案 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. 使用HTML5的网络套接字
  2. AJAX致电
  3. <强> 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/