Windows文件共享:为什么有时新创建的文件在一段时间内不可见?

时间:2011-03-01 19:17:15

标签: windows share smb

我们遇到了一个让我们发疯的非常奇怪的问题。有时我们的文件共享PC上新创建的文件在一段时间内“缺席”。要重现问题,您应至少拥有两台计算机,并将其称为alphabeta。在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 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!

我们发现错误是由枚举创建新文件的共享目录引起的。在Python调用os.listdir('//beta/share/bug')以重现错误。在C#Directory.GetDirectories(@"\\beta\share\bug")。您甚至可以直接导航到按shell共享目录,然后调用lsdir

Windows Server 2008 R2

上发现了错误

请注意,您无法在Windows资源管理器中实时查看alpha PC上的目录内容,因为如果您在资源管理器中打开此目录,则不会发生错误!因此,在尝试重现错误之前,请确保关闭所有此类窗口。每次重新启动脚本后,您应该手动从共享中删除所有已创建的文件(因为脚本相当愚蠢,始终从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
  3. 有没有人发现过类似的问题,可以解释它为什么会发生以及如何“正确修复”它?

    由于

5 个答案:

答案 0 :(得分:39)

我遇到了类似的问题,最终,我发现了这个问题的原因。具体问题是SMB2目录缓存,它是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中,这仍然是一个问题。有关详细信息,请参阅以下评论。

答案 1 :(得分:3)

一个月过去了,没有答案......

所以,我们坚持使用“Disable SMB 2.0”解决方案。至少它有效。

http://www.petri.co.il/how-to-disable-smb-2-on-windows-vista-or-server-2008.htm

答案 2 :(得分:3)

答案 3 :(得分:3)

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

以下是一个具体问题示例: \\beta$NOCSC$\share\bug\1.txt

如果您想了解更多详情,请查看此链接:

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

答案 4 :(得分:2)

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

我们注意到文件夹中有onclick="delete_slider(<?php echo $slider->id ?>);"也有帮助,即使它什么都不做。