GNU/Linux >> LINUX-Kenntnisse >  >> Linux

Abschneiden einer Datei während der Verwendung (Linux)

Ab Coreutils 7.0 gibt es einen truncate Befehl.


Das Interessante an diesen nachgewachsenen Dateien ist, dass die ersten 128 KB oder so alle Nullen sind, nachdem Sie die Datei durch Kopieren von /dev/null gekürzt haben darüber. Dies liegt daran, dass die Datei auf die Länge null gekürzt wird, der Dateideskriptor in der Anwendung jedoch immer noch unmittelbar nach dem letzten Schreibvorgang zeigt. Wenn es erneut schreibt, behandelt das Dateisystem den Anfang der Datei als reine Nullbytes – ohne die Nullen tatsächlich auf die Festplatte zu schreiben.

Idealerweise sollten Sie den Anbieter der Anwendung bitten, die Protokolldatei mit dem O_APPEND zu öffnen Flagge. Das bedeutet, dass nach dem Abschneiden der Datei beim nächsten Schreibvorgang implizit bis zum Ende der Datei gesucht wird (dh zurück zum Offset Null) und dann die neuen Informationen geschrieben werden.

Dieser Code manipuliert die Standardausgabe so, dass sie sich in O_APPEND befindet Modus und ruft dann den Befehl auf, der durch seine Argumente angegeben wird (eher wie nice Führt einen Befehl aus, nachdem sein Nice-Level angepasst wurde, oder nohup führt einen Befehl aus, nachdem die Dinge behoben wurden, sodass SIGHUP ignoriert wird).

#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <errno.h>

static char *arg0 = "<unknown>";

static void error(const char *fmt, ...)
{
    va_list args;
    int errnum = errno;
    fprintf(stderr, "%s: ", arg0);
    va_start(args, fmt);
    vfprintf(stderr, fmt, args);
    va_end(args);
    if (errnum != 0)
        fprintf(stderr, " (%d: %s)", errnum, strerror(errnum));
    putc('\n', stderr);
    fflush(0);
    exit(1);
}

int main(int argc, char **argv)
{
    int attr;
    arg0 = argv[0];

    if (argc < 2)
        error("Usage: %s cmd [arg ...]", arg0);
    if ((attr = fcntl(1, F_GETFL, &attr)) < 0)
        error("fcntl(F_GETFL) failed");
    attr |= O_APPEND;
    if (fcntl(1, F_SETFL, attr) != 0)
        error("fcntl(F_SETFL) failed");
    execvp(argv[1], &argv[1]);
    error("failed to exec %s", argv[1]);
    return(1);
}

Meine Tests waren etwas beiläufig, aber gerade genug, um mich davon zu überzeugen, dass es funktioniert.

Einfache Alternative

Billy merkt in seiner Antwort an, dass '>> ' ist der Append-Operator - und tatsächlich verwendet bash (Version 3.00.16(1)) unter Solaris 10 den O_APPEND Flag - wodurch der obige Code unnötig wird, wie gezeigt ('Black JL:' ist meine Eingabeaufforderung auf dieser Maschine):

Black JL: truss -o bash.truss bash -c "echo Hi >> x3.29"
Black JL: grep open bash.truss
open("/var/ld/ld.config", O_RDONLY)             Err#2 ENOENT
open("/usr/lib/libcurses.so.1", O_RDONLY)       = 3
open("/usr/lib/libsocket.so.1", O_RDONLY)       = 3
open("/usr/lib/libnsl.so.1", O_RDONLY)          = 3
open("/usr/lib/libdl.so.1", O_RDONLY)           = 3
open("/usr/lib/libc.so.1", O_RDONLY)            = 3
open("/platform/SUNW,Ultra-4/lib/libc_psr.so.1", O_RDONLY) = 3
open64("/dev/tty", O_RDWR|O_NONBLOCK)           = 3
stat64("/usr/openssl/v0.9.8e/bin/bash", 0xFFBFF2A8) Err#2 ENOENT
open64("x3.29", O_WRONLY|O_APPEND|O_CREAT, 0666) = 3
Black JL:

Verwenden Sie die Anhängeumleitung anstelle des obigen Wrapper-Codes ('cantrip'). Dies zeigt nur, dass, wenn Sie eine bestimmte Technik für andere (gültige) Zwecke verwenden, die Anpassung an eine andere nicht unbedingt der einfachste Mechanismus ist - obwohl es funktioniert.


Leiten Sie die Ausgabe mit>> statt> um. Auf diese Weise können Sie die Datei kürzen, ohne dass die Datei auf ihre ursprüngliche Größe zurückwächst. Vergessen Sie auch nicht, STDERR (2>&1).

umzuleiten

Das Endergebnis wäre also:myprogram >> myprogram.log 2>&1 &


Linux
  1. So verschieben Sie eine Datei unter Linux

  2. Grundlagen der Linux-Dateiberechtigungen

  3. Linux – Alles ist eine Datei?

  4. Ist die Verwendung von Rsync während der Aktualisierung der Quelle sicher?

  5. Warum wird select unter Linux verwendet

Gunzip-Befehl unter Linux

Stat-Befehl unter Linux

Was ist umask unter Linux?

So verknüpfen Sie eine Datei unter Linux per Symlink

Von Linux-Systemadministratoren häufig verwendete Linux-Befehle – Teil 5

Extrahieren Sie die tar.gz-Datei unter Linux