从新做的第二版,吊炸天!结尾增加专用版打包demo。
现在要做一件非常重要的事情,把windows下的文件完全映射到远程机器(远程机器有rsync即可),文件大小和文件数量不能影响映射效率,网络正常和话性能必须要好。
注意:这里讨论的是非cygwin环境,cygwin可以解决很多问题,但不是windows用户的标配。
首先要监测文件变化,然后实时捕获变化然后映射变化的文件。Linux内核支持inotifywait,幸好windows下也有开发,感谢github。没有比rsync更吊的东西,文件数和大小丝毫不会影响效率。windows也支持管道符。基本条件都具备可以开搞了。
这个过程中有很多坑,我就直接出结论了,inotifywait+rsync+php+bat实现,多NB懂的人自然懂,这是一个通用框架,你可以自己定义各种任务。
特点:
- 我这测试代码同步到服务器10毫秒以内,相当于直接用IDE编辑服务器文件(RSE确实也可以,和这个能是一个级别?)
- 不用怀疑安全问题,rysnc的功能数量90%的人只用到了10%。
- 整套程序是否有性能问题?不用怀疑了,全部是触发型,流数据处理都是阻塞的!
- 文件创建删除,移动,改名都是一系列事件,本程序对于一些列事件只同步一次。
- rsync同步整个目录很省事,性能也在合理范围之内(4000个文件,40MB大小,从顶层目录同步也在在毫秒级),但是经过研究搞定了只同步修改的那个文件!
- 配置文件较之前版本大幅优化,已经不能更优美了,配置中rsync项直接拼接到命令行,所以有额外参数加到这里即可,比如--port=873。
- 可以在inotifywait层设置忽略,可以在php层设置忽略(配置的ignore项),可以在rsync层设置忽略。
- 文件修改和重定向(>操作)可能是修改了文件的inode导致两次MODIFY事件,追加(>>)是一次MODIFY事件,本程序用$maxInterval变量完美解决,在$maxInterval之内同一个文件只会同步一次,(你可能会说也可以用pthreads搞定,那你去搞吧,别忘了java和php多线程编程我是专家级别)。
- windows下搞这个之前肯定没人听说过吧(我搜遍google没找到类似的东西)。
不足:
- $maxInterval以秒为单位,如果以毫秒为单位应该可以用GNU的stat解决,暂时没时间搞了。
- 如果一次同步操作时间过长后面的以队列形式按序操作,这个应该是合理的事情,除非多线程搞。
有什么问题可以自己测试,比如为什么不能用bat接收管道数据处理?为什么不用xargs之类的工具(windows有GNU整套工具)?这都是坑的范围我就不再多说什么。也不要问为什么没有删除操作。
首先安装inotifywait,地址:https://github.com/thekid/inotify-win,这里有1.6编译好的exe(旧版本有很多问题,不建议使用)
windows版rsync下载地址:https://www.itefix.no/i2/cwrsync
注意:rsync服务端需要给客户端ip加host,否则服务端会反解这个IP,这个耗时非常长,如果没有host导致结果就是连接相当慢。
最最重要的是如下两个脚本,这两个脚本是相当NB的,没有一定经验是搞不出来的。
rsyncauto.bat
@echo off inotifywait -mrq --format "%%e %%w\%%f %%T" --excludei "(\.svn(\\.+)?|\.settings(\\.+)?|\.project|.buildpath)" "C:\ares\work\java\hbase-joyport\src\joyport" "C:\ares\work\php"|php "C:\Ares\Program\cwRsync_5.3.0_Free\rsync.php"
管道接收只能自己写,xargs和类似的工具都不能用,因为你要接收的是实时监控的非连续流数据。
rsync.php
<?php error_reporting ( E_ALL ); ini_set ( 'max_execution_time', 0 ); $f = fopen ( 'php://stdin', 'r' ); stream_set_blocking ( $f, 1 ); stream_set_timeout ( $f, 86400 * 365 * 100 ); /** * key is local directory * cmd window with 150 should be good */ $map = array ( 'C:\ares\work\php\test' => array ( 'rsync' => 'test@xxx.xxx.xxx.xxx::test' ), 'C:\ares\work\php\test1' => array ( 'rsync' => 'test1@xxx.xxx.xxx.xxx::test1', 'ignore' => array ( 'log/*', 'cache/*' ) ) ); // same file will not be synced in this interval.Unit is second $maxInterval = 1; $lastTime = 0; $lastFiles = array (); $i = 0; while ( true ) { $line = trim ( fgets ( $f ) ); $line = explode ( " ", $line, 3 ); if ('ISDIR' == substr ( $line [0], - 5 )) { $line [1] .= '\\'; } $time = strtotime ( $line [2] ); if ($time - $lastTime >= $maxInterval) { $lastFiles = array (); $lastTime = $time; } foreach ( $map as $k => $v ) { if (0 === strpos ( $line [1], $k )) { if (in_array ( $line [1], $lastFiles )) { continue; } $lastFiles [] = $line [1]; $file = str_replace ( '\\', '/', substr ( $line [1], strlen ( $k ) + 1 ) ); if (! empty ( $v ['ignore'] )) { foreach ( $v ['ignore'] as $v1 ) { if (fnmatch ( $v1, $file )) { continue 2; } } } $cmd = 'set CYGWIN=nodosfilewarning && cd /d ' . $k . ' && '; $cmd .= 'rsync -avz -R -d --exclude=".svn*" --exclude=".settings*" --exclude=".buildpath" --exclude=".project" '; $cmd .= '--password-file "' . __DIR__ . '/rsync.pwd" ' . $file . ' ' . $v ['rsync']; $suffix = ''; $do = false; if (0 === strpos ( $line [0], 'MODIFY' )) { $do = true; $suffix = " => $v[rsync]"; } $i ++; echo "$i $line[0] $line[1]$suffix"; if ($do) { shell_exec ( $cmd ); } echo " ok\n"; } } } fclose ( $f );
执行效果:
第一列是自增值,第二列是操作,第三列是本地文件,"=>"符号表示进行了同步操作,符号后面是rsync的远程服务器,"ok"在本次操作完成的时候才会输出。
在使用过程中修改了n次,最终使用版本打包成一个完整的示例,需要根据自己需求自行修改。
这个监控程序是有BUG的。 因为Windows系统下面的文件可以包含空格, 另外,目录也可以包含空格。 所以bug就出在 $line = explode ( ” “, $line, 3 ); 可以修改成这样: inotifywait -mrq –format “%%e | %%w\%%f | %%T” , 然后php的部分改成 $line = explode ( ” | “, $line, 3 );
$file第一次赋值的时候有点问题,后面需要添加:
if(empty($file)){
$file=’.’;
}
if (‘ISDIR’ == substr ( $line [0], – 5 )) {
$file .= ‘/’;
}
可以加你qq,能和你聊聊吗
上面有群号,有问题直接进群问即可。
wordpress编辑需要处理转义符太麻烦,直接写评论里。最后截图操作包括新建文件改名,删除,新建文件夹改名删除,移动,包括移动到忽略的子目录(配置的ignore),编辑文件,从ignore创建文件并移出来等操作。