linux文件文件夾遞歸監控


引言

今年(2016)年初來到A公司了,剛入職的時候比較缺前端fe,就過來頂了三個月,這段時間學到了好多前端開發的知識,這些都是題外話了。期間接觸了一個很好用的前端自動化部署工具 —— fis,其中有個小功能特別好用,實時監控文件,然后同步到服務端,大大提高了開發的效率。之后轉到后端,發現大家開發測試相同模塊的時候經常會出現互相覆蓋的情況,要么就一個個的復制文件到服務器上,效率非常低下,之前為這個也開發過一個純shell版本的自動化監控同步工具文件同步監控工具后來發現純shell版本的使用體驗和擴展性能非常差,就開發了這篇文章所要介紹的php版本。

這次開發了一個規范的php composer包,使用的時候直接require即可。

實現

php版本的實現沿用了shell版本的思想,通過管道命令傳遞shell命令的結果,然后對結果做各種處理,達到我們監控文件的目的。

為了完成這個功能,首先要實現一個php版本的管道命令,這里我對resource popen ( string $command , string $mode )做了封裝,可以通過很友好的處理命令的返回值。

完成了上面的模塊,接下來就是具體的實現了,實現這里有多重友好的方式,添加多路徑遞歸監控、包含正則匹配、排除正則匹配。

pipe的開發

<?php
/**
 * php對對popen的封裝,通過回調的方式模擬管道命令
 *
 */
namespace Aizuyan\Pipe;
class Pipe
{
    /**
     * 要通過管道執行的命令
     */
    protected $command = "";
    /**
     * 回調函數,將管道數據傳遞給該函數
     */
    protected $callback = null;
    /**
     * 數據之間的分隔符
     */
    protected $delimiter = "\n";
    /**
     * 設置命令
     *
     * @param cmd string 要運行的命令
     */
    public function setCmd($cmd)
    {
        $this->command = $cmd;
        return $this;
    }
    /**
     * 設置回調函數,處理管道輸出的命令
     */
    public function setCallback(callable $cb)
    {
        $this->callback = $cb;
        return $this;
    }
    /**
     * 設置數據片段之間的分隔符
     */
    public function setDelimiter($delimiter)
    {
        $this->delimiter = $delimiter;
        return $this;
    }
    /**
     * 開始運行
     */
    public function run()
    {
        $fp = popen($this->command, "r");
        if (false === $fp) {
            throw new \RuntimeException("popen execute command failed!");
        }
        $item = "";
        while (!feof($fp)) {
            $char = fgetc($fp);
            if ($this->delimiter == $char) {
                call_user_func($this->callback, $item);
                $item = "";
            } else {
                $item .= $char;
            }
        }
        pclose($fp);
    }
}

下面是測試程序

<?php
include "vendor/autoload.php";
$test = new \Ritoyan\Pipe\Pipe();
$test->setCmd("tail -f /root/t.txt")->setCallback(function($item){
        echo "獲取內容:" . $item . "\n";
})->setDelimiter("\n")->run();

tail -f /root/t.txt這個shell命令的返回結果進行實時處理,setCallback(callable func)設置了回調函數,func的參數是shell命令的標准輸出,setDelimiter($delimiter)設置了傳入回調函數參數的分隔符,這樣就可以很容易、很任性的將輸出傳遞給回調函數了。

inotify開發

這部分代碼就不提出來了,主要就是依賴上面的Pipe然后對inotifywait -mrq --format '%w,%e,%f'命令的輸出做處理,正向逆向過濾,下面是對Inotify的調用

<?php
require "vendor/autoload.php";
$obj = new Aizuyan\Inotify\Inotify();
$obj->addExclude([
    "/swp$/",
    "/swpx$/",
    "/~$/",
    "/\d$/",
    "/swx$/"
])->setCallback(function ($item){
    echo $item["event"] . " 文件 " . $item["file"] . "\n";
})->addPaths("/datas/git/")->start();

這樣運行之后,到我們修改/datas/git目錄下的文件的時候會輸出下面的內容,可以很方便的對修改文件做定制化的處理

CREATE 文件 /datas/git/inotify/README.md
MODIFY 文件 /datas/git/inotify/README.md
MOVED_TO 文件 /datas/git/aizuyan/pinyin-1/README.md
DELETE 文件 /datas/git/aizuyan/pinyin-1/LICENSE
......

inotify-tools安裝

整個功能依賴於一個linux軟件 —— inotify-tools
centos安裝yum install inotify-tools,或者通過源碼直接安裝(文檔)嘗試在OS中安裝,發現失敗了~

如何使用

我已經將他發布到了composer倉庫中,可以輕松安裝:
composer require aizuyan/inotify,之后就可以像上面的例子一樣使用了

另外這是開發的兩個組件的github地址:Aizuyan\Pipe\PipeAizuyan\Inotify\Inotify


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM