Windows 文件共享:为什么有时新创建的文件在一段时间内不可见?
我们面临着非常奇怪的问题,让我们抓狂。有时,我们的文件共享电脑上新创建的文件会在一段时间内“不存在”。要重现问题,您应该至少有两台计算机,将它们称为 alpha
和 beta
。在 beta
PC (\\beta\share\bug
) 上创建文件共享,并从 alpha
PC 运行此 PowerShell 脚本:
param(
$sharePath="\\beta\share\bug"
)
$sharePC = ($sharePath -split '\\')[2]
$session = New-PSSession -ComputerName $sharePC
$counter = 0
while ($true) {
$fileName = $sharePath + "\$counter.txt"
Invoke-Command -Session $session -ScriptBlock {
param(
$fileName
)
"" > $fileName
} -ArgumentList $fileName
if (Test-Path $fileName) {
Write-Host "File $fileName exists" -fore Green
} else {
Write-Host "!!! File $fileName does NOT exist!" -fore Red
}
$counter = $counter + 1
Start-Sleep 2
}
启动此脚本后,您可以应该能够看到这些消息:
File \\beta\share\bug\1.txt exists
File \\beta\share\bug\2.txt exists
...
现在: 打开 cmd.exe
并运行以下命令:
if exit \\beta\share\bug\foo.txt echo 1
在大约 10 秒内,您将看到以下消息:
!!! File \\beta\share\bug\3.txt does NOT exist!
!!! File \\beta\share\bug\4.txt does NOT exist!
我们发现该错误是由枚举正在创建新文件的共享目录引起的。在 Python 中,调用 os.listdir('//beta/share/bug') 来重现错误。在C#
中:Directory.GetDirectories(@"\\beta\share\bug")
。您甚至可以简单地通过 shell 导航到共享目录并调用 ls
或 dir
。
Windows Server 2008 R2
上发现错误
请注意,您无法在 Windows 资源管理器中实时查看 alpha
PC 上的目录内容,因为如果您在资源管理器中打开此目录,错误将会出现不会发生!因此,请确保在尝试重现错误之前关闭所有此类窗口。每次脚本重新启动后,您应该手动从共享中删除所有已创建的文件(因为脚本相当愚蠢并且总是从 0.txt 开始)。
目前,我们有 2 个解决此问题的方法:
- 如果客户端看到这种情况,它会在有问题的目录中创建一些临时文件 - 在该文件神奇地出现之后。
- 禁用 SMB 2.0:http:// www.petri.co.il/how-to-disable-smb-2-on-windows-vista-or-server-2008.htm
有没有人发现过类似的问题,并可以解释为什么会发生以及如何发生“正确修复”它吗?
谢谢
We were faced with very strange issue that made us crazy. Sometimes newly created files on our File Share PC were "absent" for some period of time. To reproduce a problem you should have at least two computers, call them alpha
and beta
. Create file share on beta
PC (\\beta\share\bug
) and run this PowerShell script from alpha
PC:
param(
$sharePath="\\beta\share\bug"
)
$sharePC = ($sharePath -split '\\')[2]
$session = New-PSSession -ComputerName $sharePC
$counter = 0
while ($true) {
$fileName = $sharePath + "\$counter.txt"
Invoke-Command -Session $session -ScriptBlock {
param(
$fileName
)
"" > $fileName
} -ArgumentList $fileName
if (Test-Path $fileName) {
Write-Host "File $fileName exists" -fore Green
} else {
Write-Host "!!! File $fileName does NOT exist!" -fore Red
}
$counter = $counter + 1
Start-Sleep 2
}
After starting this script you should be able to see these messages:
File \\beta\share\bug\1.txt exists
File \\beta\share\bug\2.txt exists
...
And now:
Open cmd.exe
and run this command:
if exist \\beta\share\bug\foo.txt echo 1
After this during approx 10 seconds you'll see following messages:
!!! File \\beta\share\bug\3.txt does NOT exist!
!!! File \\beta\share\bug\4.txt does NOT exist!
We've discovered that bug is caused by enumerating shared directory where new files are being created. In Python
call os.listdir('//beta/share/bug')
to reproduce a bug. In C#
: Directory.GetDirectories(@"\\beta\share\bug")
. You can even simply navigate to share directory by shell and call ls
or dir
.
Bug were found on Windows Server 2008 R2
Note, that you cannot watch directory content on alpha
PC in Windows Explorer in real time, because if you open this directory in Explorer bug would not occur! So ensure to close all such windows before attempts to reproduce a bug. After each script restart you should manually remove all already created files from share (because script is rather stupid and always starts from 0.txt).
We currently have 2 workarounds for this issue:
- If client sees this situation, it creates some temporary file in problematic directory - after this files magically appear.
- Disable SMB 2.0: http://www.petri.co.il/how-to-disable-smb-2-on-windows-vista-or-server-2008.htm
Does anybody have ever discovered similar problem and can explain why it occurs and how "correctly fix" it?
Thanks
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
我也遇到了类似的问题,最终我找到了这个问题的原因。具体问题是 SMB2 目录缓存,它是 SMB2 客户端重定向器缓存组件:
这个奇妙的小缓存的默认值为 10 秒,这会产生您所看到的行为。当您的代码向系统询问该目录/文件时,它会获取缓存的结果,该结果是 10 秒前的结果,因此它表示该文件不存在。将
HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\Lanmanworkstation\Parameters\DirectoryCacheLifetime
(DWORD) 设置为值0
将禁用缓存并解决文件不存在问题。令人惊讶的是,此更改不需要需要重新启动客户端计算机!这还允许您保持 SMB2 启用,出于多种原因,这应该比强制 SMB1 更好。此外,当在 Windows 资源管理器中打开相关共享时,不会使用缓存,因为打开它会告诉系统绕过缓存以保持实时视图的运行。但是,通过代码修改共享中的某些内容则不然。
我认为整个问题在 Windows 2008 R2/7 及更高版本中已得到解决,但我不能绝对确认。这仍然是现代版本 Windows 中的一个问题。详情请参阅下面的评论。I was experiencing a similar problem and, eventually, I found the cause of this issue. The specific problem is the SMB2 Directory Cache, which is one of the SMB2 Client Redirector cache components:
The default value for this wonderful little cache is 10 seconds, which is producing the behavior you're seeing. When your code asks the system about that directory/file it's getting the cached result, which is 10 seconds old, so it says the file does not exist. Setting
HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\Lanmanworkstation\Parameters\DirectoryCacheLifetime
(DWORD) to a value of0
will disable the cache and resolve the file doesn't exist issue. Surprisingly this change does not require a restart of the client machine! This will also allow you to keep SMB2 enabled, which should be better for a number of reasons vs. forcing SMB1.Furthermore, the cache is not used when the share in question is opened in Windows explorer, as having it open tells the system to bypass the cache to keep a live view going. Modifying something in the share via code, however, does not.
I think this whole issue is fixed in Windows 2008 R2/7 and higher, but I cannot absolutely confirm it.This is still an issue in modern versions of Windows. See the comments below for details.一个月过去了,没有任何答复...
因此,我们继续使用“
禁用 SMB 2.0
”解决方案。至少它有效。http:// /www.petri.co.il/how-to-disable-smb-2-on-windows-vista-or-server-2008.htm
A month passed and no answer...
So, we stayed with "
Disable SMB 2.0
" solution. At least it works.http://www.petri.co.il/how-to-disable-smb-2-on-windows-vista-or-server-2008.htm
Windows 7 SP1 中还存在一个错误,有可用的修补程序
用户添加的文件在运行 Windows 7 或 Windows Server 2008 R2 的计算机上的 Windows 资源管理器中不显示远程文件夹
There is also a bug in Windows 7 SP1 for which there is a hotfix available
File that a user adds to a remote folder is not displayed in Windows Explorer on a computer that is running Windows 7 or Windows Server 2008 R2
您可以使用神奇的后缀
$NOCSC$
,而不是像其他人建议的那样通过注册表项禁用 SMB 或缓存。这将允许您保持所有 Windows 设置不变,但同时文件将不会被缓存。这是一个问题的具体示例:
\\beta$NOCSC$\share\bug\1.txt
如果您想了解更多详细信息,请查看此链接:
http://blog.wisefaq.com/2016/01/26/nocscno-client-side-caching/
You can use magical suffix
$NOCSC$
, instead of disabling SMB or caching via registry keys, as some others suggested. This will allow you to leave all Windows settings intact, but at the same time files will not get cached.Here is a question specific example:
\\beta$NOCSC$\share\bug\1.txt
Check this link if you want more details:
http://blog.wisefaq.com/2016/01/26/nocscno-client-side-caching/
解决此问题的最简单方法(按照OP的建议)是在您希望文件出现的文件夹中创建一个临时文件或子文件夹,并立即将其删除。这会触发变化变得可见。
我们注意到,在文件夹中添加
FileSystemWatcher
也有帮助,即使它什么也不做。The easiest way to work around this (as suggested by the OP) is to create a temporary file or subfolder in the folder where you expect the files to appear and remove it right away. This triggers the change to become visible.
We noticed that having a
FileSystemWatcher
in the folder also helps, even when it does nothing.