25

我们面临着非常奇怪的问题,这让我们发疯了。有时,我们的文件共享 PC 上新创建的文件在一段时间内“不存在”。要重现问题,您应该至少拥有两台计算机,调用它们alphabeta. beta在PC ( )上创建文件共享\\beta\share\bug并从 PC 运行此 PowerShell 脚本alpha

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

请注意,您不能alpha在 Windows Explorer 中实时查看 PC 上的目录内容,因为如果您在 Explorer 中打开此目录,则不会出现错误!因此,请确保在尝试重现错误之前关闭所有此类窗口。每次脚本重新启动后,您应该手动从共享中删除所有已创建的文件(因为脚本相当愚蠢并且总是从 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

有没有人发现过类似的问题并且可以解释它为什么会发生以及如何“正确修复”它?

谢谢

4

5 回答 5

41

我遇到了类似的问题,最终我找到了这个问题的原因。具体问题是 SMB2 目录缓存,它是SMB2 客户端重定向器缓存组件之一:

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

这个美妙的小缓存的默认值为 10 秒,这会产生您所看到的行为。当您的代码向系统询问有关该目录/文件的信息时,它会获得 10 秒前的缓存结果,因此它说该文件不存在。将HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\Lanmanworkstation\Parameters\DirectoryCacheLifetime(DWORD) 设置为值0将禁用缓存并解决文件不存在问题。令人惊讶的是,此更改不需要重新启动客户端计算机!这也将允许您保持启用 SMB2,与强制 SMB1 相比,出于多种原因,这应该更好。

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

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

于 2012-03-29T23:35:25.783 回答
4

一个月过去了,还是没有回音……

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

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

于 2011-03-31T18:01:50.910 回答
3

Windows 7 SP1 中还有一个错误,有可用的修补程序

用户添加到远程文件夹的文件不会显示在运行 Windows 7 或 Windows Server 2008 R2 的计算机上的 Windows 资源管理器中

于 2015-02-17T19:24:24.030 回答
3

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

这是一个特定于问题的示例: \\beta$NOCSC$\share\bug\1.txt

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

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

于 2016-12-09T10:08:41.700 回答
2

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

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

于 2016-02-02T16:02:55.163 回答