Linux - 防止应用程序因磁盘空间不足而失败

Linux - 防止应用程序因磁盘空间不足而失败

由于不可预测的情况,我目前需要找到解决方案来解决应用程序(我不想杀死它)正在慢慢占用整个磁盘空间的情况。提供更多背景信息

  • 我有一个 Python 应用程序,它使用 multiprocessing.Pool 来启动 5 个线程。每个线程将一些数据写入自己的文件。

  • 该程序在 Linux 上运行,我没有机器的 root 访问权限。

  • 该程序是 CPU 密集型的并且已经运行了几个月。还有几天时间来写入所有数据。

  • 文件中40%的数据是冗余的,经过快速测试后可以删除。

  • 运行该程序的系统只有 30GB 的剩余磁盘空间,按照当前的工作速度,在程序完成之前它肯定会被占用。

鉴于上述几点,我看到以下针对各自问题的解决方案

  • 鉴于进程号 i 正在写入 file_i,将 file_i 移动到外部位置是否安全?操作系统会简单地创建一个新的 file_i 实例并写入它吗?我认为移动文件会删除它,并且该过程最终会写入“死”文件?

  • 是否有一种“命令行”方法可以停止 5 个生成的工作人员中的 4 个,并等到其中一个工作人员完成后再恢复工作? (我确信一个工作线程可以避免占用磁盘)

  • 假设我使用 CTRL+Z 冻结主进程。这会停止 multiprocessing.Pool 产生的所有其他进程吗?如果是,我可以安全地编辑文件以删除多余的行吗?

鉴于我看到的三个选项,其中任何一个都可以在这种情况下工作吗?如果没有,是否有更好的方法来处理这个问题?我真的很想避免程序在完成前几天崩溃的情况。

答案1

如果将文件移动到不同的文件系统,幕后发生的情况是复制文件的当前内容并删除原始文件。如果程序仍在写入文件,它将继续写入现已删除的文件。已删除但已打开的文件实际上并未被删除,而只是被分离(它不再有名称);当程序关闭该文件时,该文件将被真正删除。因此,您会遇到两全其美的情况:文件仍然使用尽可能多的磁盘空间,但您会丢失剩余的输出。

您可以按Ctrl+Z暂停前台进程,然后使用命令bg或恢复它fg。所有线程都被挂起,除非程序经历了一些其他的行为。 (旨在通过网络生成子进程的程序可能会表现出不同的行为。单进程多线程程序很可能表现正常。)如果程序由不同的进程组成,请使用命令ps来定位它们全部以及类似kill -STOP 1234 1238 1239挂起的命令它们全部(用于kill -CONT …稍后恢复它们)。

如果程序在文件中写入甚至来回读取,您就无法在其眼皮子底下删除其数据。在此阶段移动数据可能是可行的,但会很困难,并且取决于程序的工作方式。但根据您的描述,该程序可能只是不断附加到每个文件,在这种情况下,可以在开始时删除一些数据。

不要编辑文件:这不太可能达到您想要的效果。大多数编辑器的工作方式是保存新文件并将其移动到旧文件的位置(这在保存时发生崩溃的情况下更可靠)。您可以通过截断文件的开头来节省磁盘空间。首先,复制文件以将数据保存在其他位置。然后将文件截断为长度0。程序将继续在之前的位置追加;如果该位置是 12345,那么一旦程序附加另一个字节,文件就会以 12345 个空字节开始。大多数空字节不会占用任何磁盘空间:该文件将是稀疏文件

# Suspend the program first, otherwise you'll lose output produced between cp and truncation!
for x in *.out; do
  cp "$x" /elsewhere/
  : >|"$x"  # truncate $x to size 0
done

程序完成后,您可以将剩余的数据附加到其他地方保存的文件中。这tail实用程序可以复制省略第一个文件的文件字节;请注意,该参数是要省略的字节数加一。

for x in *.out; do
  existing_size=$(stat -c %s "/elsewhere/$x")
  tail -c +$((existing_size+1)) "$x" >>"/elsewhere/$x"
done

如果您有 rsync 3.0.0 或更高版本,则可以使用

rsync --append *.out /elsewhere/

请注意,旧的 rsync 版本会使用源中新出现的空字节覆盖文件的现有部分!在执行此操作之前检查您的 rsync 版本。

答案2

如果没有 root 访问权限,您的选择非常有限。恕我直言,您最好的选择,也是唯一现实的成功机会,是压缩已经写入和关闭的文件,并希望这样做可以释放足够的空间供您的程序完成。 SO 上的人们可能还有其他选择,你试过在那里问吗?

答案3

鉴于进程号 i 正在写入 file_i,将 file_i 移动到外部位置是否安全?操作系统会简单地创建一个新的 file_i 实例并写入它吗?我认为移动文件会删除它,并且该过程最终会写入“死”文件?

如果程序不断打开文件,写入数据,然后再次关闭,那么是的,您只需移动该文件,它就会创建一个新文件。大多数程序不是这样工作的。操作系统可能会显示文件已被移动,但实际上占用了磁盘空间,直到程序关闭文件句柄。

是否有一种“命令行”方法可以停止 5 个生成的工作人员中的 4 个,并等到其中一个工作人员完成后再恢复工作? (我确信一个工作线程可以避免占用磁盘)

这将取决于程序使用的工作线程类型,并且您几乎肯定需要根访问权限(您可能必须使用调试工具,并且确切的顺序将高度依赖于程序的工作方式)。如果没有 root 访问权限和对程序内部运作的深入了解,这可能是不可行的。

假设我使用 CTRL+Z 冻结主进程。这会停止 multiprocessing.Pool 产生的所有其他进程吗?如果是,我可以安全地编辑文件以删除多余的行吗?

再次取决于程序的运行方式。暂停进程很可能也会暂停工作人员,但这并不能保证。但是,我不认为这会改变问题,因为文件句柄的文件指针仍将指向与编辑文件之前相同的偏移量。


您可以将任何其他文件移出系统吗?或者这是一个可以扩展虚拟磁盘的虚拟机?

相关内容