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

问题描述

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

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

lsof | grep deleted

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

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

一旦我停止运行 Flask 应用程序,lsof 将没有此文件,并且空间将被回收。

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

在 Internet 上搜索“打开但已删除文件”时,大多数建议是“找到该应用程序并杀死它”。有没有办法让 Flask 应用程序保持运行而不重新启动它?我的应用程序实际上并没有“打开”这个文件,只是简单地 os.remove 它。

关于如何删除文件并立即收回空间的建议?

解决方法

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() 类似于我的示例,以找出应该关闭特定文件的期望值不匹配的地方。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...