cat /dev/null > file.log 不会在 Darwin 中截断大文件

chb*_*chb 14 logs darwin

过去,在 linux 系统上,我已经能够使用cat /dev/null > file.log.

但是,在 10.9(小牛队)上,情况似乎并非如此。我有一个 11GB 的文件正在被应用程序记录,但是当我对所述文件执行相同的命令时,似乎没有任何反应。

当我在一个很小的文件上尝试这个时,它确实有效。

这是ls -l /dev/null

crw-rw-rw- 1 root wheel 3, 2 Dec 16 12:49 /dev/null

我也试过cp /dev/null file.log没有用。

考虑到我可能会利用 truncate 函数(man 2 truncate在 Darwin 中),我编译了它并针对两个文件运行它,一个是小文件,另一个是实际的日志文件。同样,它对普通文件有效,对更大的日志无效。

/*
 * Copyright (c) 2013 Thomas de Grivel <thomas@lowh.net>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 ...
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */

#include <unistd.h>

int main (int argc, const char **argv)
{
        int e = 0;
        while (--argc) {
                argv++;
                if (truncate(*argv, 0)) {
                        e = 4;
                        warn("%s", *argv);
                }
        }
        return e;
}
Run Code Online (Sandbox Code Playgroud)

0无论我使用哪个文件,该过程都会返回。

Sté*_*las 12

cat /dev/null编写不产生输出的命令的方法有点复杂。:或者true是更明显的。

在所有cat /dev/null > file: > file甚至> file大多数 shell 中,shell 在 stdout 上打开带有 O_TRUNC 的文件,然后运行不输出任何内容的应用程序,然后文件被关闭并被截断。

但是,在这种情况下或使用truncate系统调用时,如果正在填充该文件的进程没有使用 O_APPEND 标志打开它,则下次它写入已在文件上打开的文件描述符时,它将写入它在文件中的偏移量处的数据。

因为 HFS+ 不支持稀疏文件,这意味着系统必须重新分配该偏移量之前的空间并用零填充。

因此,您需要在截断它之前终止正在写入该文件的应用程序。或者您需要确保应用程序打开文件O_APPEND(就像>>使用外壳重定向一样)。

如果你想尝试一下:

$ exec 3> x
$ yes | head -n 50000 >&3
$ ls -ls x
200 -rw-r--r--  1 me me  100000 Dec 16 21:32 x
Run Code Online (Sandbox Code Playgroud)

现在我的 shell 的 fd 3 是文件中的 100000 字节

$ : > x
$ ls -ls x
0 -rw-r--r--  1 me me  0 Dec 16 21:34 x
Run Code Online (Sandbox Code Playgroud)

现在文件被截断(大小为 0,磁盘上没有空间使用)。

$ echo >&3
$ ls -ls x
200 -rw-r--r--  1 me me  100001 Dec 16 21:34 x
Run Code Online (Sandbox Code Playgroud)

在偏移量 100000 处向文件写入 1 个字节,文件现在有 100001 个字节大,第一个全为零,在 HFS+ 上将使用超过 100k,但在大多数其他 Unix 文件系统中大约只有一个磁盘块

另一方面,与:

$ exec 3>> x
$ yes | head -n 50000 >&3
$ ls -ls x
200 -rw-r--r--  1 me me  100000 Dec 16 21:35 x
$ : > x
$ echo >&3
$ ls -ls x
8 -rw-r--r--  1 me me  1 Dec 16 21:36 x
Run Code Online (Sandbox Code Playgroud)

向文件写入 1 个字节不是在偏移量 100000 处,而是在文件末尾,因为O_APPEND. 该文件有 1 个字节大,并占用了容纳该 1 个字节所需的空间。