cat / dev / null> file.log schneidet große Dateien in Darwin nicht ab

15

In der Vergangenheit konnte ich auf Linux-Systemen große, offene Protokolldateien (d. H. Eine Datei, in die ein Prozess aktiv schreibt) mit abschneiden cat /dev/null > file.log.

Bei 10.9 (Mavericks) scheint dies jedoch nicht der Fall zu sein. Ich habe eine 11-GB-Datei, auf die sich eine Anwendung anmeldet, aber wenn ich denselben Befehl mit dieser Datei ausführe, scheint nichts zu passieren.

Wenn ich das mit einer Datei von trivialer Größe versuche, funktioniert es.

Hier ist ls -l /dev/null:

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

Ich habe auch erfolglos versucht cp /dev/null file.log.

Da ich dachte, ich könnte die Truncate-Funktion ( man 2 truncatein Darwin) nutzen, kompilierte ich diese und führte sie für zwei Dateien aus, eine von unbedeutender Größe und die andere für die eigentliche Protokolldatei. Wiederum funktionierte es gegen die Trivialdatei und nicht für das viel größere Protokoll.

/*
 * Copyright (c) 2013 Thomas de Grivel <[email protected]>
 *
 * 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;
}

Der Prozess kehrt zurück, 0unabhängig davon, welche Datei ich verwende.

chb
quelle
Woher weißt du, dass es nicht funktioniert hat? Was macht duoder du -hsagt? Ist es möglich, dass es sich bei der Datei um eine Sparse-Datei handelt?
Mikel
2
Was ist der Zweck, eine Lizenz in diesen Beitrag aufzunehmen? Es scheint nur Rauschen hinzuzufügen.
Mikel
du -h /tmp/file.logErgebnisse in11G /tmp/file.log
chb
@Mikel Ich habe die Lizenz mit freundlicher Genehmigung beigefügt ... Sie werden feststellen, dass ich das meiste davon redigiert habe.
chb
1
Die Lizenz ist eine Ablenkung, das wahre Juwel hier ist die Antwort
iruvar

Antworten:

12

cat /dev/nullist ein etwas verschlungener Weg, um einen Befehl zu schreiben, der keine Ausgabe erzeugt. :oder truesind offensichtlicher.

In allen cat /dev/null > file, : > fileund auch > filein den meisten Muscheln, die Shell - Datei mit O_TRUNC auf stdout öffnet, dann die Anwendung läuft , die nicht ausgegeben etwas tut, dann wird die Datei geschlossen und links abgeschnitten.

Wenn jedoch in diesem Fall oder bei Verwendung des truncateSystemaufrufs der Prozess, der diese Datei füllt, sie nicht mit dem Flag O_APPEND öffnet, wird sie beim nächsten Schreiben in den Dateideskriptor, den sie für die Datei geöffnet hat, geschrieben Die Daten mit dem Versatz, der sich in der Datei befand.

Da HFS + keine Sparse-Dateien unterstützt, muss der Speicherplatz vor diesem Offset vom System neu zugewiesen und mit Nullen gefüllt werden.

Sie müssen also die Anwendung beenden, die in diese Datei schreibt, bevor Sie sie abschneiden. Oder Sie müssen sicherstellen, dass die Anwendung die Datei mit öffnet O_APPEND(wie bei >>Verwendung der Shell-Umleitung).

Wenn Sie damit experimentieren möchten:

$ exec 3> x
$ yes | head -n 50000 >&3
$ ls -ls x
200 -rw-r--r--  1 me me  100000 Dec 16 21:32 x

Jetzt ist die FD 3 meiner Shell 100000 Bytes in der Datei

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

Jetzt wird die Datei abgeschnitten (Größe 0, kein Speicherplatz auf der Festplatte).

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

Wenn Sie 1 Byte mit dem Offset 100000 in die Datei schreiben, ist die Datei jetzt 100001 Byte groß. Die ersten Nullen würden unter HFS + über 100 KB belegen, in den meisten anderen Unix-Dateisystemen jedoch nur etwa einen Plattenblock

Andererseits mit:

$ 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

Schreiben von 1 Byte in die Datei nicht bei Offset 100000, sondern am Ende der Datei wegen O_APPEND. Die Datei ist 1 Byte groß und benötigt den für dieses Byte erforderlichen Speicherplatz.

Stéphane Chazelas
quelle
1
Ich habe so viel aus dieser Antwort gelernt. Vielen Dank.
chb