sed 在完整文件系统上就地行删除?

Wil*_*ard 12 sed text-processing files ed

由于尚未诊断的应用程序错误,我有数百个磁盘已满的服务器。有一个文件被重复的行填满——不是日志文件,而是一个带有变量定义的用户环境文件(所以我不能直接删除该文件)。

我编写了一个简单的sed命令来检查错误添加的行并删除它们,并在文件的本地副本上对其进行了测试。它按预期工作。

但是,当我在带有完整磁盘的服务器上尝试它时,我得到了大约以下错误(它来自内存,而不是复制和粘贴):

sed: couldn't flush /path/to/file/sed8923ABC: No space left on deviceServerHostname
Run Code Online (Sandbox Code Playgroud)

当然,我知道没有剩余空间了。这就是为什么我试图删除东西!(sed我使用的命令会将 4000 多行的文件减少到大约 90 行。)

我的sed命令只是sed -i '/myregex/d' /path/to/file/filename

尽管磁盘已满,有没有办法可以应用此命令?

(它必须是自动化的,因为我需要将它应用到数百台服务器上作为快速修复。)

(显然需要诊断应用程序错误,但同时服务器无法正常工作......)


更新:通过删除我发现可以删除的其他内容来解决我面临的情况,但我仍然希望得到这个问题的答案,对未来和其他人都有帮助。

/tmp是不行的;它在同一个文件系统上。

在释放磁盘空间之前,我进行了测试,发现可以vi通过打开文件并运行来删除其中的行:g/myregex/d,然后使用:wq. 似乎应该可以自动执行此操作,而无需求助于单独的文件系统来保存临时文件......(?)

Bar*_*mar 10

-i选项并没有真正覆盖原始文件。它使用输出创建一个新文件,然后将其重命名为原始文件名。由于您在文件系统上没有此新文件的空间,因此它失败了。

您需要在脚本中自己执行此操作,但要在不同的文件系统上创建新文件。

此外,如果您只是删除与正则表达式匹配的行,则可以使用grep代替sed.

grep -v 'myregex' /path/to/filename > /tmp/filename && mv /tmp/filename /path/to/filename
Run Code Online (Sandbox Code Playgroud)

一般来说,程序很少可能使用相同的文件作为输入和输出——一旦它开始写入文件,从文件中读取的程序部分将不再看到原始内容。因此,它要么首先将原始文件复制到某处,要么写入新文件并在完成后重命名。

如果不想使用临时文件,可以尝试将文件内容缓存在内存中:

file=$(< /path/to/filename)
echo "$file" | grep -v 'myregex' > /path/to/filename
Run Code Online (Sandbox Code Playgroud)

  • @Hastur `sed -i` 不保留任何这些东西。我只是用一个我不拥有的文件尝试了它,但它位于我拥有的目录中,它让我替换了该文件。替换物归我所有,而不是原主人。 (2认同)
  • @Barmar - 你不知道它是否有效 - 你甚至不知道你已经成功打开输入。您至少可以做的是`v=$(&lt;file)&amp;&amp; printf %s\\n "$v" &gt;file`,但您甚至不使用`&amp;&amp;`。提问者谈论的是在脚本中运行它 - 自动用文件本身的一部分覆盖文件。您至少应该验证您可以成功打开输入和输出。此外,外壳可能会爆炸。 (2认同)

cha*_*aos 4

就是这样sed工作的。如果与-i(就地编辑)一起使用sed,则会创建一个包含已处理文件的新内容的临时文件。完成后sed,用临时文件替换当前工作文件。该实用程序不会就地编辑文件。这正是每个编辑的行为。

这就像您在 shell 中执行以下任务:

sed 'whatever' file >tmp_file
mv tmp_file file
Run Code Online (Sandbox Code Playgroud)

此时sed,尝试使用系统调用将缓冲数据刷新到错误消息中提到的文件中fflush()

对于输出流,fflush()通过流的底层写入函数强制写入给定输出或更新流的所有用户空间缓冲数据。


对于您的问题,我看到了一个解决方案,安装一个单独的文件系统(例如tmpfs,如果您有足够的内存,或外部存储设备)并将一些文件移到那里,在那里处理它们,然后将它们移回来。


归档时间:

查看次数:

9604 次

最近记录:

4 年,3 月 前