Unix中用于截断大文件的shell脚本

92

我正在尝试编写一个Unix脚本,当一个应用程序不断地写入/打开一个文件并占用3GB空间时,该脚本将截断/清空该文件。我知道下面的命令可以做到:

cp /dev/null [filename]

但我将以定时器方式在生产环境中自动运行此程序 - 我在这里发布,想知道您是否在执行类似操作时遇到任何问题。


这些是生产日志,没有价值吗?我很幸运能够保存我的生产日志一年以上(以bzip2 -9格式),并且有一些小工具可以轻松提取作业运行时间、处理的记录以及加载到电子表格中后容易计算和绘制加载比率和其他一些东西。由于负载比率下降,我们发现了一个硬件问题。是的,有很多可爱的监控工具,所以这完全取决于您的情况。作为另一种选择,您是否看过logrotate,它可能会为您提供一些价值(但设置可能会很烦人(只是猜测)!)。 - shellter
5
请注意,如果使用O_APPEND标志打开日志文件,则截断操作将生效。如果没有使用O_APPEND标志打开,则程序将在第一次写入时从3 GiB偏移量继续写入;系统将把前3 GiB视为全字节零(可压缩),但文件将继续增长。这完全取决于编写日志的程序。 - Jonathan Leffler
5个回答

128

只是为了补充另一个答案,

: > filename
:在bash(符合POSIX标准)中是一个无操作命令,因此它本质上只是打开文件进行写入(当然会截断文件),然后立即关闭文件。

编辑:如shellter所评论的,实际上您不需要使用重定向附带任何命令:

$ echo foo > foo.txt
$ cat foo.txt
foo
$ > foo.txt
$ cat foo.txt
$

一个简单的重定向本身将清除文件。


8
"@shelter":“$ > file” 不符合 POSIX 标准,也不具备可移植性。建议在重定向之前使用“:”无操作命令,正如最初提出的那样。 - Aaron Toponce
4
+加号代表微笑的表情 - Chris Suszyński
5
正如 @AaronToponce 指出的那样,"$ > file" 在不同系统上并不通用;在我的Zsh设置中,它会让shell挂起(似乎在等待输入)。"$ : > file" 在Zsh中运行正常。 - Linus Arver
1
@TechEnthusiast 这取决于您的期望。截断本身是原子性的,但您不知道它相对于任何特定写入何时发生。例如,您可能最终在文件开头得到一个部分行。 - chepner
2
操作在文件系统级别进行序列化,但写入不一定是原子性的,而截断则是。例如,如果一个进程执行 echo "foo bar",而另一个进程截断该文件,则可能会有三个操作:write "foo "truncatewrite "bar"。(尽管这样一个小的写操作被拆分的几率很小,但不为零。然而,截断是保证作为一个单一、不可中断的操作完成的。) - chepner
显示剩余9条评论

68

我在Debian上使用了以下命令

truncate -s 0 filename

@SteveClay:sudo sh -c ': > filename'也会截断filename - Perleone
2
@SteveClay OP的建议也可以完美地与sudo一起使用:sudo cp /dev/null filename。此外,cp是可移植的,而truncate仅适用于现代Linux系统。 - Tino

12

我觉得这听起来很合理。当然,Unix会让你以大约50种不同的方式做到这一点。以下是两个例子:

echo -n "" >filename
cat /dev/null >filename

或许第一行就足以截取文件了。 - Timo
1
@Timo - 同意。我修改了我的回复以增加清晰度。 - Don Branson

3

截取文件名 filename

适用于 UNIX 的 AIX 版本。


0

还有一种替代方案:

dd count=0 of=文件名

优势(主要适用于嵌入式系统):

  • 因为没有重定向,所以不需要生成 shell(bash、dash 等)
  • 与 busybox 兼容

dd 工具是什么? - ryanwebjackson
1
"man dd" 是指 "dd - 转换和复制文件"。 这个工具来自GNU coreutils或busybox。很可能始终存在于所有的Linux发行版,甚至包括Android/toybox。 - Richard Buchmann

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接