Как заставить IIS7 выпустить заблокированный файл?


25

Во время наших производственных сборок очень большой (10 мегабайт) файл статического содержимого в корневом каталоге иногда блокируется IIS и не может быть удален чистой задачей. Вероятно, это связано с тем, что в данный момент он активно обслуживается одним или несколькими клиентами.

Процесс сборки останавливает сайт перед очисткой через

c:\Windows\System32\inetsrv\appcmd.exe stop site http://oursite.com

Однако это не освобождает файл - мы должны перезапустить IIS, чтобы процесс снял свою блокировку.

appcmd.exeпозволяет полностью отключить IIS; мы не хотим этого делать!

Существуют ли другие способы заставить IIS освободить заблокированный файл без перезапуска IIS? Простая остановка и запуск отдельного сайта определенно не работает, чтобы снять блокировку файла.


1
Серьезный вопрос сейчас: этот статический файл меняется от сборки к сборке или это просто файл, который никогда не изменится?
splattne

Просто сумасшедшая мысль, но мне интересно, что произойдет, если вы включите теневые копии в этой папке?
Ричард Вест

Это ваш sitemap.xml, верно?
Дейв Чейни

Да, это был наш sitemap.xml, но теперь у нас просто есть MVC-маршрут к нему и кеш-память в памяти. Нет больше блокировки!
Джаррод Диксон

Ответы:


12

Существуют инструменты, такие как Process Explorer в Sysinternal, которые могут находить и принудительно закрывать дескрипторы файлов, однако состояние и поведение приложения (как вашего, так и, в данном случае, IIS) после этого не определено. Некоторых это не волнует, некоторые будут ошибаться, а другие будут сильно падать.

Правильное решение состоит в том, чтобы отключить систему и позволить IIS аккуратно снять блокировки и очистить после себя, чтобы сохранить стабильность сервера. Если это невозможно, вы можете либо создать другой сайт в том же блоке, либо создать новый блок с новым контентом и переместить доменное имя / IP-адрес для «продвижения» нового контента в производство.


2
+1 для проводника процессов, он может дать вам некоторое представление о том, как решить проблему, если вы увидите, какой поток держит дескриптор файла открытым
Ник Кавадиас

Может быть, очень полезно освободить заблокированный файл программно с помощью инструментов Sysinternals с Powershell , C # или сценариев bat-cmd
Kiquenet

У меня есть IIS, чтобы разблокировать файл или каталог, просто пытаясь скопировать файлы в эту контролируемую IIS папку и затем просмотреть веб-приложение в браузере. Иногда этот процесс открывает эти ручки.
Марк полдень

13

Я использую небольшой инструмент под названием «Ручка», чтобы сделать это.

Вы в основном передаете ему имя файла, который заблокирован, и он сообщает вам, какие процессы его используют:

handle c:\weird.file
Something.exe pid: 1000 100: C:\weird.file
Something.exe pid: 1000 101: C:\weird.file

Затем вы передаете ему ключ -c, чтобы он закрывал дескриптор:

handle.exe -c 101 -p 1000 -y
handle.exe -c 100 -p 1000 -y

Вы можете изо всех сил работать над этим в сценарии сборки без программы-обертки для анализа вывода, но, надеюсь, это поможет.


Могучий Марк Руссинович на помощь - я это проверю, но ужасное предупреждение Хэндла о нестабильности программы при принудительном закрытии ручки заставляет меня нервничать.
Джаррод Диксон

Надеемся, что любая нестабильность будет ограничена соответствующим AppPool. Если это так, то вы можете просто перезагрузить AppPool после снятия блокировки.
Саймон Джонсон

@ Джаррод: удачи? Не могли бы вы опубликовать какие-либо результаты, в ваш оригинальный пост, пожалуйста? Я хотел бы видеть, что происходит здесь, за кулисами.
Pure.Krome

Может быть, очень полезно освободить заблокированный файл программным способом , используя Handle с Powershell , C # или скриптами bat-cmd и получить процессы, которые блокируют папку
Kiquenet

5

Я не уверен, если вы имеете в виду компиляцию файлов aspx во временных сборках. Мы используем проекты развертывания ASP.NET , которые предварительно компилируют все файлы aspx / ascx.

При копировании двоичных файлов из папки «publish» в папку «bin» мы временно включаем файл app_offline.htm, который удаляется после копирования всех сборок (всего несколько секунд). Таким образом, я никогда не сталкивался с блокировками файлов.

РЕДАКТИРОВАТЬ:

Вы можете попытаться перезапустить пул приложений, используя appcmd.exe, вместо остановки веб-сайта:

C:\Windows\System32\inetsrv\appcmd.exe recycle apppool "My App Pool Name"

1
Нет, это просто файл статического содержимого в корневом каталоге - обновите вопрос этой информацией!
Джаррод Диксон

1
Я полагаю, вы используете app_offline.htm во время выполнения задания по сборке?
splattne

Я думаю, что мы пробовали перерабатывать вручную безрезультатно, но попробуем еще раз в следующий раз, когда будет блокировка (пулы приложений для .NET, верно? Вероятно, здесь не поможет). И раньше мы создавали файл app_offline.htm, но это не помогло с блокировкой - вот почему мы перешли к отключению отдельного сайта.
Джаррод Диксон

Боюсь, ты прав. Я протестирую это на одном из наших серверов и вернусь к вам.
splattne

1
@splattne: переработка пула приложений должна была удалить дескриптор при условии, что файл был открыт веб-сайтом. Если переработка пула не помогает, то я предполагаю, что что-то еще блокирует файл.
ПБЗ


1

Process Monitor должен помочь вам с вашим расследования, вот пример из блога Марка ( на парня , который написал инструмент) о том , как найти дескриптор файла.

Вы можете попробовать этот инструмент Unlocker для автоматизации разблокировки на уровне дескриптора файла.


Круто, я никогда не использовал Process Monitor; но каждая рабочая станция, которую я использую, немедленно получает Process Explorer! technet.microsoft.com/en-us/sysinternals/bb896653.aspx
Джаррод Диксон

1

Не ответ, а обходной вариант, если нет способа «разблокировать» этот файл без перезапуска сервера IIS:

Что если вы соберете / развернете новую пустую папку и измените домашнюю папку веб-сайта на эту папку? Вы должны создать новое имя папки или переключаться между двумя именами.

Я не знаю, к какой папке принадлежит этот файл. Если он не должен находиться в корневой папке, вы можете поместить его во вновь созданную папку и создать виртуальный каталог, указывающий на эту папку. Таким образом, вы можете сохранить свой стандартный домашний каталог для приложения.


1

У меня такая же проблема. Теперь я переключился на MSDeploy (Web Deploy) , и теперь я могу надежно обновлять веб-сайт, ничего не останавливая. На самом деле этот шаг написан на скрипте в нашем автоматизированном инструменте сборки, и это происходит постоянно без проблем. И это тоже быстро.


0

Конечно, остановите службу IIS. Может я чего-то не понимаю, извините.


2
Если вы остановите службу IIS, вы отключите все веб-сайты ...
splattne

Это единственное, чего мы действительно хотим избежать, так как мы не хотим, чтобы наш сайт CruiseControl.NET закрывался - мы нажимаем эту кнопку «Обновить статус», как безумцы, во время сборки, чтобы проверить успешность!
Джаррод Диксон

Хорошо, как насчет сборки сначала где-то еще, а затем развертывания поверх статического файла вместо того, чтобы делать все на этом сервере?
Марк Аллен

разве это не проблема здесь? Никто не сказал, что файл был изменен программным обеспечением на самом сервере.
FlavorScape

0

примечание: не эксперт по семантике блокировки файлов Windows

Джаррод, вы можете переименовать файл с пути. Вы также можете создать новый файл с временным расширением, а затем переименовать его поверх текущего файла.

Если семантика блокировки файлов Windows работает аналогично семантике POSIX, читатели, которые удерживают текущую блокировку чтения файла, должны продолжать обслуживать старый файл, пока они не закроют свои потоки чтения, пока новые читатели откроют новый файл.


Нет, мы ничего не можем сделать с файлом, пока IIS не будет перезапущен.
Джаррод Диксон
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.