一个flask网站,当它删除一个文件(os.remove("abc.txt"))时,文件被删除但是space没有被回收

A flask website, when it delete a file (os.remove("abc.txt")), the file is removed but the space is not reclaimed

该程序是一个标准的 flask 程序,它会在初始化过程中进行一些清理工作。在 cleanup() 过程中,使用 os.remove("abc.txt"),我注意到文件已被删除,但未被 OS 回收。 我在 运行 应用程序中同时使用“python website.py”和“gunicorn website:app”,并且在 Linux 环境中都有同样的问题。在 Mac 中OS,我无法复制它。

文件为 os.remove 后,它不再在“ls”命令中列出,但是当我 运行

lsof | grep deleted

我仍然可以看到此文件被列为已删除但被 python 应用程序打开。

因为这个文件已经是“os.remove”,所以不在ls命令中列出,du不会计算这个文件。 但是如果这个文件足够大,df命令会显示这个文件的space还在被占用,没有被回收。因为这个文件仍然“被烧瓶应用程序打开”,正如 lsof 程序所声称的那样。

一旦我从 运行ning 停止 flask 应用程序,lsof 将没有这个文件,并且 space 被回收。

通常当文件太小,或者应用程序频繁停止或重启时,您不会注意到space被占用。但这对于保留 space 来说并不是很合理。我希望网站 运行 宁年。

在互联网上搜索“打开但已删除的文件”时,大多数建议是“找到应用程序并将其终止”。有没有办法让 flask 应用程序保持 运行ning 而无需重新启动它?我的应用程序实际上并没有“打开”这个文件,只是 os.remove 它。

关于如何立即删除文件并重新声明 space 的建议?

Flask 应用程序需要大文件才能继续运行,或者不释放不需要的资源。 如果应用程序需要大文件,就是这样。否则,该应用程序有问题,需要更正。 在这两种情况下,大文件的“正在打开”状态(至少在 Linux 导致文件仍然存在于大容量内存系统中)无法由您的脚本控制。

os.remove() 仅将删除文件委托给操作系统。如果该文件仍在您的代码中引用的某处,lsof 当然会显示该文件。如果不提供代码,就很难判断不良行为的来源。但至少我可以给你一些关于引用行为的见解。

这是一个小脚本,它应该只向您显示文件在被引用时仍可被视为打开。

import os
import psutil

PATH = "abc.txt"


def write_file(filepath):
    """Simulating existing file with correctly closing it at the end"""
    with open(filepath, "x") as file:
        file.write("Hello, world!")


def remove_file(filepath):
    """Let the operating system handle the file removement"""
    os.remove(filepath)


def lsof():
    """Simulating lsof command (requires e.g. `pip install psutil`)"""
    p = psutil.Process()
    open_files = p.open_files()
    if open_files:
        return "\n".join(os.path.basename(p.path) for p in p.open_files())
    else:
        return "No open files found."


if __name__ == "__main__":
    print("\n----- EXAMPLE 1 -----\n")

    write_file(PATH)
    print(lsof())
    remove_file(PATH)
    print(lsof())

    print("\n----- EXAMPLE 2 -----\n")

    write_file(PATH)
    file = open(PATH)  # referenced!
    print(lsof())
    remove_file(PATH)
    print(lsof())

示例 2 的输出显示,在引用文件后,它也可用于 lsof 命令:

----- EXAMPLE 1 -----

No open files found.
No open files found.

----- EXAMPLE 2 -----

abc.txt
No open files found.

这两个示例还向您展示了删除文件后不再有打开的文件描述符。

您也许可以尝试调试您的代码,例如psutil.Process.open_files() 类似于我的示例,以找出应该关闭特定文件的预期不匹配的地方。