在我们的生产构建过程中,根目录中的一个非常大(10 兆字节)的静态内容文件有时会被 IIS 锁定,并且无法被清理任务删除。这可能是因为它当时正在积极地服务于一个或多个客户。
在清理之前,构建过程会停止网站
c:\Windows\System32\inetsrv\appcmd.exe stop site http://oursite.com
但是,这不会释放文件 - 我们必须重新启动 IIS 才能让进程放弃其锁定。
appcmd.exe
允许您完全关闭 IIS;我们不想这样做!
有没有其他方法可以让 IIS 在不重新启动 IIS 的情况下释放锁定的文件?简单地停止和启动单个网站绝对不能释放文件锁定。
我使用一个名为“Handle”的小工具来做到这一点。
您基本上将被锁定文件的名称传递给它,它会告诉您哪些进程正在使用它:
然后将 -c 开关传递给它以使其关闭句柄:
您可能很难在没有包装程序的情况下将其用于构建脚本来解析输出,但希望这会有所帮助。
有一些工具,例如 Sysinternal 的 Process Explorer,可以找到并强制关闭文件句柄,但是执行此操作后应用程序(包括您的,在本例中为 IIS)的状态和行为是未定义的。有些人不在乎,有些人会出错,有些人会严重崩溃。
正确的解决方案是中断并允许 IIS 干净地释放锁并自行清理以保持服务器稳定性。如果这不可行,您可以在同一个盒子上创建另一个站点,或者设置一个包含新内容的新盒子,然后移动域名/IP 以“促进”新内容投入生产。
我不确定你的意思是不是在临时程序集中编译 aspx 文件。我们正在使用ASP.NET 部署项目,它预先编译所有 aspx/ascx 文件。
在将二进制文件从“publish”复制到“bin”文件夹时,我们临时启用了一个 app_offline.htm 文件,该文件在复制所有程序集后被删除(只需几秒钟)。这样我就从来没有经历过文件锁。
编辑:
您可以尝试使用 appcmd.exe 回收应用程序池,而不是停止网站:
我现在正在尝试这个:如果您在目录上激活了索引,显然可能存在文件锁定问题。 http://www.richard-banks.org/2008/04/how-to-fix-problems-with-locked-files.html
这是 IIS 6.0,但由于这似乎与操作系统有关,而不是 IIS,因此它可能是根本原因。
Process Monitor应该可以帮助您进行调查,这是Mark 的博客(编写该工具的人)中有关如何查找文件句柄的示例。
您可能想尝试使用此Unlocker 工具在文件句柄级别自动解锁。
不是答案,而是一种解决方法,以防在不重新启动 IIS 服务器的情况下无法“解锁”该文件:
如果您构建/部署到一个新的空文件夹并将网站的主目录更改为该文件夹怎么办?您必须创建一个新的文件夹名称或在两个名称之间切换。
我不知道该文件属于哪个文件夹。如果它不必在根文件夹中,您可以将它放在新创建的文件夹中并创建一个指向该文件夹的虚拟目录。因此,您可以保留应用程序的标准主目录。
我有同样的问题。现在我切换到MSDeploy (Web Deploy),现在我可以在不停止任何操作的情况下可靠地更新网站。事实上,这一步是在我们的自动构建工具中编写的,它一直在发生,没有任何问题。而且它也很快。
当然,停止 IIS 服务。也许我不明白什么,对不起。
注意:不是 Windows 文件锁定语义方面的专家
Jarrod,你能把文件重命名吗?您也可以使用临时扩展名创建新文件,然后将其重命名为当前文件。
如果 Windows 文件锁定语义的工作方式与 POSIX 类似,则持有文件当前读取锁定的读取器仍应继续提供旧文件,直到关闭其读取流,而新读取器将打开新文件。