cat / dev / null> file.log не усекает большой файл в Дарвине

15

Раньше в системах Linux я мог обрезать большие открытые файлы журналов (то есть файл, который активно записывается процессом) с использованием cat /dev/null > file.log.

Тем не менее, на 10,9 (Mavericks), это не так. У меня есть файл размером 11 ГБ, в который регистрируется приложение, но когда я выполняю ту же команду с указанным файлом, кажется, ничего не происходит.

Когда я пробую это на файле тривиального размера, это работает.

Вот ls -l /dev/null:

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

Я также пытался cp /dev/null file.logбезрезультатно.

Думая, что я мог бы воспользоваться функцией усечения ( man 2 truncateв Дарвине), я скомпилировал это и запустил для него два файла, один из которых имеет тривиальный размер, а другой - сам файл журнала. Снова, это работало против тривиального файла и не работало на намного большем журнале.

/*
 * 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;
}

Процесс возвращается 0независимо от того, какой файл я использую.

БКИ
источник
Откуда ты знаешь, что это не сработало? Что duили du -hсказать? Возможно ли, что файл является разреженным файлом?
Микель
2
Кроме того, какова цель включения лицензии в этом посте? Кажется, только добавляет шума.
Микель
du -h /tmp/file.logРезультаты:11G /tmp/file.log
CHB
@Mikel Я включил лицензию в качестве любезности ... вы заметите, что я отредактировал большую часть ее.
ЧБ
1
лицензия отвлекает, истинная жемчужина здесь - ответ
iruvar

Ответы:

12

cat /dev/nullнемного запутанный способ написать команду, которая не производит вывод. :или trueболее очевидные.

Во всех cat /dev/null > file, : > fileи даже > fileв большинстве оболочек, оболочка открывает файл с 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

Теперь fd 3 моей оболочки составляет 100000 байт в файле

$ : > x
$ ls -ls x
0 -rw-r--r--  1 me me  0 Dec 16 21:34 x

Теперь файл урезан (размер 0, на диске нет места).

$ echo >&3
$ ls -ls x
200 -rw-r--r--  1 me me  100001 Dec 16 21:34 x

Записывая 1 байт в файл со смещением 100000, размер файла теперь составляет 100001 байт, первые из них, все нули, будут использовать более 100 Кбайт в HFS +, но примерно в одном блоке диска в большинстве других файловых систем 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

Запись 1 байта в файл не по смещению 100000, а в конце файла из-за O_APPEND. Файл имеет размер 1 байт и занимает место, необходимое для хранения этого одного байта.

Стефан Шазелас
источник
1
Я так много узнал из этого ответа. Благодарю.
2013 г.