2011-03-01 34 views
21

我们遇到了非常奇怪的问题,让我们发疯。有时我们的文件共享PC上新创建的文件在一段时间内“缺席”。要重现问题,您应该至少有两台计算机,请将其称为alphabetabeta PC(\\beta\share\bug)上创建文件共享,并从alpha PC运行此PowerShell脚本:Windows文件共享:为什么有时候新创建的文件在某段时间内不可见?

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 exist \\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! 

我们已经发现这个bug是通过列举其中正在创建新的文件共享目录引起的。在Python请致电os.listdir('//beta/share/bug')重现一个错误。在C#Directory.GetDirectories(@"\\beta\share\bug")。你甚至可以简单地导航到shell共享目录,并呼吁lsdir

错误是在Windows Server 2008 R2

注意发现,你不能alpha在电脑上观看目录中的内容在Windows资源管理器中实时,因为如果你打开在资源管理器的bug这个目录就不会发生!因此,确保在尝试重现错误之前关闭所有这些窗口。每次脚本重新启动后,您应手动从共享中删除所有已创建的文件(因为脚本相当愚蠢,始终从0.txt开始)。

我们目前有2个解决方法针对此问题:

  1. 如果客户看到这种情况下,它会在有问题的目录中的一些临时文件 - 此文件后,奇迹般地出现。
  2. 禁用SMB 2.0:http://www.petri.co.il/how-to-disable-smb-2-on-windows-vista-or-server-2008.htm

是否有人曾经发现了类似的问题,可以解释它为什么会发生,以及如何“正确地解决”吗?

感谢

+0

你看网络跟踪,看看这是怎么回事? – selbie 2011-03-02 08:52:54

+0

不,不幸的是,我没有看过网络跟踪 – Roman 2011-03-02 16:08:01

+0

我不认为网络跟踪会有所帮助。这似乎是服务器端的缓存问题。从Windows 2003到2012R2,我们遇到了完全相同的问题。看来SMB为创建它们的服务器显示了文件,但随后显示这些文件还不存在于查询它们的其他服务器。这很糟糕。 – Brain2000 2015-01-04 02:10:25

回答

36

我正经历着类似的问题,最终,我发现这个问题的原因。具体问题是SMB2 Directory Cache,它是SMB2 Client Redirector cache components之一:

这是由客户端执行的最新目录枚举的缓存。客户端应用程序的后续枚举请求以及目录中文件的元数据查询可以通过缓存来满足。客户端还使用目录高速缓存来确定目录中是否存在文件,并使用该信息来防止客户端反复尝试打开已知不存在于服务器上的文件。此缓存可能会影响在多台计算机上运行的分布式应用程序,这些计算机访问服务器上的一组文件 - 应用程序使用带外机制相互通知服务器上文件的修改/添加/删除。

这个美妙的小缓存的默认值是10秒,这产生了你所看到的行为。当你的代码向系统询问该目录/文件时,它会得到缓存的结果,它的结果是10秒钟,所以它说该文件不存在。将HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\Lanmanworkstation\Parameters\DirectoryCacheLifetime(DWORD)设置为值0将禁用缓存并解决文件不存在问题。令人惊讶的是,这个变化确实需要重新启动客户端机器而不是!这也可以让你保持启用SMB2,由于许多原因,这与强制SMB1相比应该更好。

此外,当在Windows资源管理器中打开有问题的共享时,不使用缓存,因为打开缓存会告诉系统绕过缓存以保留实时视图。但是,通过代码修改共享中的内容不会。

我认为整个问题在Windows 2008 R2/7及更高版本中都已修复,但我无法绝对确认它。这仍然是现代Windows版本中的一个问题。详细信息请参见下面的评论。

+5

它在2008R2和更高版本中不是固定的。实际上,它仍然是Windows 2012R2中的一个问题。 – Brain2000 2015-01-04 02:11:43

+0

顺便说一句,这个解决方案解决了通过SMB共享访问Windows 2012R2的机器的问题。谢谢Justin,您的信息非常有价值! – Brain2000 2015-01-04 02:24:57

+0

@ Brain2000感谢您确认这在以后的版本中仍然是个问题。 – 2015-01-04 21:15:40

2

来解决这个(由OP的建议),最简单的方法是创建一个临时文件或您希望文件出现的文件夹中的子文件夹,并立即将其删除。这会触发更改变为可见。

我们注意到,在文件夹中有FileSystemWatcher也有帮助,即使它什么都不做。

+0

可笑,因为它听起来,这是对我来说最简单的答案(我作为用户浏览,而不是自动化) – Basic 2016-03-08 00:25:30

2

您可以使用神奇的后缀$NOCSC$,而不像其他人建议的那样通过注册表项禁用SMB或缓存。这将允许您保持所有Windows设置不变,但同时文件不会被缓存。

这里有一个问题,具体的例子: \\beta$NOCSC$\share\bug\1.txt

检查,如果你想了解更多详细信息,点击此链接:

http://blog.wisefaq.com/2016/01/26/nocscno-client-side-caching/

相关问题