Подтвердить что ты не робот

Общий ресурс Windows: почему иногда созданные файлы не отображаются в течение некоторого периода времени?

Мы столкнулись с очень странной проблемой, которая сделала нас сумасшедшими. Иногда недавно созданные файлы на нашем ПК с файловым доступом "отсутствовали" в течение некоторого периода времени. Чтобы воспроизвести проблему, у вас должно быть как минимум два компьютера, назовите их alpha и beta. Создайте общий ресурс файла на beta ПК (\\beta\share\bug) и запустите этот PowerShell script с 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
}

После запуска этого script вы должны будете видеть эти сообщения:

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"). Вы даже можете просто перейти к общему каталогу с помощью оболочки и вызвать ls или dir.

Ошибка была найдена на Windows Server 2008 R2

Обратите внимание, что вы не можете просматривать содержимое каталога на alpha ПК в проводнике Windows в режиме реального времени, потому что если вы откроете этот каталог в Explorer, ошибка не возникнет! Поэтому убедитесь, что вы закрываете все такие окна перед попытками воспроизвести ошибку. После каждого перезапуска script вы должны вручную удалить все уже созданные файлы из share (потому что script довольно глупо и всегда начинается с 0.txt).

В настоящее время у нас есть 2 способа обхода проблемы:

Кто-нибудь когда-либо обнаружил подобную проблему и может объяснить, почему это происходит и как "правильно исправить" это?

Спасибо

4b9b3361

Ответ 1

У меня возникла аналогичная проблема, и, в конце концов, я нашел причину этой проблемы. Конкретной проблемой является SMB2 Directory Cache, который является одним из Компоненты кэширования редиректора клиента SMB2:

Это кеш последних списков, выполняемых клиентом. Последующие запросы перечисления, сделанные клиентскими приложениями, а также запросы метаданных для файлов в каталоге, могут быть выполнены из кеша. Клиент также использует кеш каталога, чтобы определить наличие или отсутствие файла в каталоге и использует эту информацию, чтобы клиенты не пытались открывать файлы, которые, как известно, не существуют на сервере. Этот кеш, вероятно, повлияет на распределенные приложения, запущенные на нескольких компьютерах, обращающихся к набору файлов на сервере, - где приложения используют внеполосный механизм, чтобы сигнализировать друг другу об изменении/добавлении/удалении файлов на сервере.

Значение по умолчанию для этого замечательного маленького кеша составляет 10 секунд, что создает поведение, которое вы видите. Когда ваш код запрашивает систему об этом каталоге/файле, он получает кешированный результат, который составляет 10 секунд, поэтому он говорит, что файл не существует. Установка HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\Lanmanworkstation\Parameters\DirectoryCacheLifetime (DWORD) на значение 0 отключит кеш и разрешить файл не существует. Удивительно, но это изменение не требует перезагрузки клиентской машины! Это также позволит вам поддерживать SMB2 включенным, что должно быть лучше по ряду причин или для принудительного SMB1.

Кроме того, кеш не используется, когда раскрывающийся ресурс открывается в проводнике Windows, так как его открывание сообщает системе обходить кеш, чтобы сохранить просмотр в реальном времени. Однако, чтобы изменить что-то в share через код, это не так.

Я думаю, что вся эта проблема исправлена ​​в Windows 2008 R2/7 и выше, но я не могу ее полностью подтвердить. Это все еще проблема в современных версиях Windows. Подробнее см. Ниже.

Ответ 4

Самый простой способ обойти это (как предлагает OP) - создать временный файл или подпапку в папке, где вы ожидаете появления файлов и сразу же удалить их. Это приводит к тому, что изменение становится видимым.

Мы заметили, что наличие FileSystemWatcher в папке также помогает, даже когда ничего не делает.

Ответ 5

Вы можете использовать магический суффикс $NOCSC$ вместо отключения SMB или кеширования с помощью разделов реестра, как предложили некоторые другие. Это позволит вам оставить все настройки Windows неповрежденными, но в то же время файлы не будут кэшироваться.

Вот пример конкретного вопроса: \\beta$NOCSC$\share\bug\1.txt

Проверьте эту ссылку, если хотите получить более подробную информацию:

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