Closed osdu closed 6 years ago
@celeron533
user-rule.ini??
@wongsyrone 我自己修改扩展名了,txt 不能语法高亮。 我试过官方版本都有同样的问题
第一张图是官方版本的,后两张是我自己修改后编译的版本,都有同样的问题。
这是我的修改记录 https://github.com/osdu/shadowsocks-windows-for-anmpserver/commits/master
以前为了能实时按照user-rule更新PAC,使用了FileSystemWatcher b2c2d05c940cf7249c3597274cd5a3281b93749b 怀疑
UserRuleFileWatcher = new FileSystemWatcher(Directory.GetCurrentDirectory());
UserRuleFileWatcher.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.FileName | NotifyFilters.DirectoryName;
UserRuleFileWatcher.Filter = USER_RULE_FILE;
UserRuleFileWatcher.Changed += UserRuleFileWatcher_Changed;
UserRuleFileWatcher.Created += UserRuleFileWatcher_Changed;
UserRuleFileWatcher.Deleted += UserRuleFileWatcher_Changed;
UserRuleFileWatcher.Renamed += UserRuleFileWatcher_Changed;
UserRuleFileWatcher.EnableRaisingEvents = true;
在处理的时候发生了意外
现存代码还有段dirty hack ...
@celeron533 这个好像会受到 gfwlist.txt 和 user-rule.txt 所含内容或者是文件大小的影响,具体原因不明。 我没学过 .Net 没能力深入排查,还望大神给解决下。
因为平时做PHP开发,需要翻墙的网站不多,就想重新定制一份精简的 gfwlist.txt,在精简gfwlist.txt过程中发现这个问题。
@osdu 如果仅限于浏览器的话,chrome系的可以用switchyomega自定义代理切换规则 https://github.com/FelisCatus/SwitchyOmega/releases
有详细的重现过程吗? 主要是user-rule的文件大小还是gfwlist的文件大小? 如果使用经典notepad.exe是否会有这样的问题?记得notepad++不是使用独占模式打开的文件
另外notepad++在打开文件后,可以手动指定语法高亮的语言的
@celeron533
使用我修改后的 gfwlist.txt
替换 ss_win_temp
目录下的 gfwlist.txt
, 然后编辑 user-rule.txt
,打开自动生成的pac文件可以看到gfwlist.txt
里边的规则解析出来了,但是 user-rule.txt
里边的自定义规则却没生效。
gfwlist.txt 内如如下
W0F1dG9Qcm94eSAwLjIuOV0KISBDaGVja3N1bTogMzAyM2t1NEV1Y1ZpZFJMQUZLb3ZDdwohIEV4
cGlyZXM6IDZoCiEgVGl0bGU6IEdGV0xpc3Q0TEwKISBHRldMaXN0IHdpdGggRVZFUllUSElORyBp
bmNsdWRlZAohIExhc3QgTW9kaWZpZWQ6IFNhdCwgMTkgQXVnIDIwMTcgMDI6MjQ6MjQgLTA0MDAK
IQohIEhvbWVQYWdlOiBodHRwczovL2dpdGh1Yi5jb20vZ2Z3bGlzdC9nZndsaXN0CiEgTGljZW5z
ZTogaHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL2dmd2xpc3QvZ2Z3bGlzdC9tYXN0
ZXIvQ09QWUlORy50eHQKIQohIEdGV0xpc3QgaXMgdW5saWtlbHkgdG8gZnVsbHkgY29tcHJpc2Ug
dGhlIHJlYWwKISBydWxlcyBiZWluZyBkZXBsb3llZCBpbnNpZGUgR0ZXIHN5c3RlbS4gV2UgdHJ5
CiEgb3VyIGJlc3QgdG8ga2VlcCB0aGUgbGlzdCB1cCB0byBkYXRlLiBQbGVhc2UKISBjb250YWN0
IHVzIHJlZ2FyZGluZyBVUkwgc3VibWlzc2lvbiAvIHJlbW92YWwsCiEgb3Igc3VnZ2VzdGlvbiAv
IGVuaGFuY2VtZW50IGF0IGlzc3VlIHRyYWNrZXI6CiEgaHR0cHM6Ly9naXRodWIuY29tL2dmd2xp
c3QvZ2Z3bGlzdC9pc3N1ZXMvLgoKIS0tLS0tLS0tLTQwMy80NTEvNTIwICYgVVJMIFJlZGlyZWN0
cy0tLS0tLS0tLQp8fDJkYm9vay5jb20KfHw0dGVybi5jb20KCiEtLS0tLS0tLS0tLS0tLS0tLS0t
LS1FT0YtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLQo=
复现视频链接 https://www.youtube.com/watch?v=tMVFOW-CsnQ
只在 user-rule.ini
增删空格,在视频50-55 秒之间可看到 pac.txt
体积在 22KB
到 61KB
之间变化
gfwlist.txt
规则始终是生效的,user-rule.ini
是否生效毫无规律可言
用vscode编辑user-rule.txt,发现依旧存在两次保存的现象,第一次清空了文件,第二次把新内容存了进去。 目前的PAC生成逻辑在某些情况下仅被第一次保存行为激发,而忽略第二次
https://stackoverflow.com/a/1765094/2075611
Notepad writes to the disk in batches that create the content of the file and then the file attributes. Other applications may perform in the same manner.
@celeron533 做个延时处理能否解决这个问题? 就是检测到改后做500ms延时,保证编辑器顺利写入user-rule.txt文件后再重写读入user-rule.txt内容
刚测试过管用,至于有没有其他副作用就不清楚了 https://github.com/osdu/shadowsocks-windows-for-anmpserver/commit/4ead4113ff2e0da14f3d204fc01564d7e32cc3c0
@celeron533 貌似可以了,只是看不明白 currentLastWriteTime string 改成 DateTime 就可以了?
感觉 shadowsocks-csharp/Data/proxy.pac.txt.gz 暂时没必要更新,改完就和 abp.js.gz 功能重复了
proxy.pac.txt.gz 不应该更新的。没关系,是我自己的repo,过会儿force push掉。 currentLastWriteTime.ToString() 的时候会掉精度,所以后面的判断语句在某些情况下会认为两次FileChange都是同一时刻,而忽略第二次的event。可惜在有些文本编辑器上是先清空文件再重写内容,此时重写的内容就被忽略。 但如果保持精度的话,那个关于时间的IF判断就变得没用了,因为几乎不可能相同
另一个方案
// DateTime only has millisecond resolution
// these two DateTimes are used as long as the program is running
private static DateTime _pacLastWriteDateTime = DateTime.MinValue;
private static DateTime _userRuleLastWriteDateTime = DateTime.MinValue;
// make the timespan sane for checking in case we catch events multiple times
private static readonly TimeSpan LastWriteCheckSpan = TimeSpan.FromSeconds(1);
private void PACFileWatcher_Changed(object sender, FileSystemEventArgs e)
{
var path = e.FullPath;
DateTime lastWriteTime = File.GetLastWriteTime(path);
if (lastWriteTime - _pacLastWriteDateTime > LastWriteCheckSpan)
{
if (PACFileChanged != null)
{
Logging.Info($"Detected: PAC file {e.Name} {e.ChangeType}.");
PACFileChanged(this, new EventArgs());
}
_pacLastWriteDateTime = lastWriteTime;
}
}
private void UserRuleFileWatcher_Changed(object sender, FileSystemEventArgs e)
{
var path = e.FullPath;
DateTime lastWriteTime = File.GetLastWriteTime(path);
if (lastWriteTime - _userRuleLastWriteDateTime > LastWriteCheckSpan)
{
if (UserRuleFileChanged != null)
{
Logging.Info($"Detected: User Rule file {e.Name} {e.ChangeType}.");
UserRuleFileChanged(this, new EventArgs());
}
_userRuleLastWriteDateTime = lastWriteTime;
}
}
@wongsyrone 这个写法可能还是有逻辑问题,假设_userRuleLastWriteDateTime为2分钟前最后一次读写,你开了文本编辑器再次保存文件(触发2次change),按照目前逻辑第一次change的时差为2分钟,第二次change时差和前次只有几毫秒,不会走进if语句吧。所以第二次保存依旧被miss掉。 每次保存的时候将文件相关对象保存到一个变量(多次change这个文件仅保留最后一次记录)并启动唯一计时器,特定延时后保存
事实上两次change的原因是第一次保存文件,第二次修改文件属性,比如修改lastwrite等。第一次已经足够了,不用区分两次触发。
使用vscode编辑文件:
各种文本编辑器有各种不同的行为,头痛。
我这有一些有趣的log
[2017-08-28 09:49:43] Detected: PAC file pac.txt Created 736568.09:49:43.1066383. [2017-08-28 09:49:49] Detected: User Rule file user-rule.txt Created 736568.09:49:49.7043727. [2017-08-28 09:50:02] Detected: User Rule file user-rule.txt Changed 00:00:12.4706746. [2017-08-28 09:50:02] Detected: PAC file pac.txt Changed 00:00:19.0864094. [2017-08-28 09:50:02] Detected: PAC file pac.txt Changed 00:00:00.0010021. [2017-08-28 09:50:35] Detected: User Rule file user-rule.txt Changed 00:00:32.8794936. [2017-08-28 09:50:35] Detected: PAC file pac.txt Changed 00:00:32.8674470. [2017-08-28 09:50:35] Detected: PAC file pac.txt Changed 00:00:00.0010008. [2017-08-28 09:50:40] Detected: User Rule file user-rule.txt Deleted -152180.01:50:35.0545409. [2017-08-28 09:51:17] Detected: PAC file pac.txt Deleted -152180.01:50:35.0624976. [2017-08-28 09:59:25] Detected: PAC file pac.txt Created 2017/8/28 9:59:25. [2017-08-28 09:59:46] Detected: User Rule file user-rule.txt Created 2017/8/28 9:59:46. [2017-08-28 09:59:54] Detected: User Rule file user-rule.txt Changed 2017/8/28 9:59:54. [2017-08-28 09:59:54] Detected: PAC file pac.txt Changed 2017/8/28 9:59:54. [2017-08-28 09:59:58] Detected: User Rule file user-rule.txt Changed 2017/8/28 9:59:58. [2017-08-28 09:59:58] Detected: PAC file pac.txt Changed 2017/8/28 9:59:58. [2017-08-28 09:59:58] Detected: PAC file pac.txt Changed 2017/8/28 9:59:58. [2017-08-28 10:00:04] Detected: User Rule file user-rule.txt Deleted 1601/1/1 8:00:00. [2017-08-28 10:00:05] Detected: PAC file pac.txt Deleted 1601/1/1 8:00:00. [2017-08-28 10:07:48] Detected: PAC file pac.txt Created. [2017-08-28 10:07:48] Detected: PAC file pac.txt Changed 2017/8/28 10:07:48. [2017-08-28 10:08:14] Detected: User Rule file user-rule.txt Created. [2017-08-28 10:08:14] Detected: User Rule file user-rule.txt Changed 2017/8/28 10:08:14. [2017-08-28 10:08:58] Detected: User Rule file user-rule.txt Changed 2017/8/28 10:08:58. [2017-08-28 10:08:58] Detected: PAC file pac.txt Changed 2017/8/28 10:08:58. [2017-08-28 10:09:01] Detected: User Rule file user-rule.txt Changed 2017/8/28 10:09:01. [2017-08-28 10:09:01] Detected: PAC file pac.txt Changed 2017/8/28 10:09:01. [2017-08-28 10:09:05] Detected: User Rule file user-rule.txt Deleted. [2017-08-28 10:09:06] Detected: PAC file pac.txt Deleted. [2017-08-28 10:10:54] Detected: PAC file pac.txt Created. [2017-08-28 10:11:04] Detected: User Rule file user-rule.txt Created. [2017-08-28 10:11:25] Detected: User Rule file user-rule.txt Changed 2017/8/28 10:11:25. [2017-08-28 10:11:25] Detected: PAC file pac.txt Changed 2017/8/28 10:11:25. [2017-08-28 10:11:29] Detected: User Rule file user-rule.txt Changed 2017/8/28 10:11:29. [2017-08-28 10:11:29] Detected: PAC file pac.txt Changed 2017/8/28 10:11:29. [2017-08-28 10:11:31] Detected: User Rule file user-rule.txt Deleted. [2017-08-28 10:11:32] Detected: PAC file pac.txt Deleted.
改过的代码
// DateTime only has millisecond resolution
// these two DateTimes are used as long as the program is running
private static DateTime _pacLastWriteDateTime = DateTime.MinValue;
private static DateTime _userRuleLastWriteDateTime = DateTime.MinValue;
// make the timespan sane for checking in case we catch Changed events multiple times
private static readonly TimeSpan LastWriteCheckSpan = TimeSpan.FromMilliseconds(2);
private void PACFileWatcher_Changed(object sender, FileSystemEventArgs e)
{
if (e.ChangeType == WatcherChangeTypes.Created ||
e.ChangeType == WatcherChangeTypes.Deleted ||
e.ChangeType == WatcherChangeTypes.Renamed)
{
_pacLastWriteDateTime = DateTime.Now;
if (PACFileChanged != null)
{
Logging.Info($"Detected: PAC file {e.Name} {e.ChangeType}.");
PACFileChanged(this, new EventArgs());
}
return;
}
var path = e.FullPath;
DateTime lastWriteTime = File.GetLastWriteTime(path);
var timeDiff = lastWriteTime - _pacLastWriteDateTime;
if (timeDiff > LastWriteCheckSpan)
{
_pacLastWriteDateTime = lastWriteTime;
if (PACFileChanged != null)
{
Logging.Info($"Detected: PAC file {e.Name} {e.ChangeType}.");
PACFileChanged(this, new EventArgs());
}
}
}
private void UserRuleFileWatcher_Changed(object sender, FileSystemEventArgs e)
{
if (e.ChangeType == WatcherChangeTypes.Created ||
e.ChangeType == WatcherChangeTypes.Deleted ||
e.ChangeType == WatcherChangeTypes.Renamed)
{
_userRuleLastWriteDateTime = DateTime.Now;
if (UserRuleFileChanged != null)
{
Logging.Info($"Detected: User Rule file {e.Name} {e.ChangeType}.");
UserRuleFileChanged(this, new EventArgs());
}
return;
}
var path = e.FullPath;
DateTime lastWriteTime = File.GetLastWriteTime(path);
var timeDiff = lastWriteTime - _userRuleLastWriteDateTime;
if (timeDiff > LastWriteCheckSpan)
{
_userRuleLastWriteDateTime = lastWriteTime;
if (UserRuleFileChanged != null)
{
Logging.Info($"Detected: User Rule file {e.Name} {e.ChangeType}.");
UserRuleFileChanged(this, new EventArgs());
}
}
}
@celeron533
做了下延时处理,使用一天,貌似一切正常
Thread.Sleep(250);
做了下延时处理,使用一天,貌似一切正常
以后再看看有没有更“优雅”的方法
目前官方关于FileSystemWatcher两次执行的讨论 https://github.com/dotnet/corefx/issues/25117
gfwlist.txt 修改后 user-rule.txt 会随机失效,user-rule.txt 中随便添加几个空格又会随机生效
gfwlist.txt 大批量删除规则重新保存后会出现这个问题
修改后的 gfwlist.txt
local 会出现随机为空的情况