GNU/Linux >> Znalost Linux >  >> Linux

Zkrácení souboru během jeho používání (Linux)

Od coreutils 7.0 existuje truncate příkaz.


Zajímavá věc na těchto přerostlých souborech je, že prvních 128 KB nebo tak bude po zkrácení souboru zkopírováním /dev/null samé nuly přes to. K tomu dochází, protože soubor je zkrácen na nulovou délku, ale deskriptor souboru v aplikaci stále ukazuje bezprostředně po jeho posledním zápisu. Když se znovu zapisuje, systém souborů považuje začátek souboru za všechny nulové bajty – aniž by ve skutečnosti nuly zapisoval na disk.

V ideálním případě byste měli požádat dodavatele aplikace, aby otevřel soubor protokolu s O_APPEND vlajka. To znamená, že poté, co soubor zkrátíte, další zápis bude implicitně hledat konec souboru (což znamená zpět na nulový posun) a poté zapíše nové informace.

Tento kód upravuje standardní výstup, takže je v O_APPEND mode a poté vyvolá příkaz daný jeho argumenty (spíše jako nice spustí příkaz po úpravě jeho úrovně nice, neboli nohup spustí příkaz po opravě, takže ignoruje SIGHUP).

#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);
}

Moje testování bylo poněkud náhodné, ale jen stěží natolik, aby mě přesvědčilo, že to funguje.

Jednodušší alternativa

Billy ve své odpovědi poznamenává, že '>> ' je operátor append – a skutečně na Solaris 10 bash (verze 3.00.16(1)) používá O_APPEND flag - čímž se výše uvedený kód stává zbytečným, jak je znázorněno ("Black JL:" je moje výzva na tomto počítači):

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:

Spíše než výše uvedený kód wrapper ('cantrip') použijte přesměrování typu append. To jen dokazuje, že když používáte jednu konkrétní techniku ​​pro jiné (platné) účely, její přizpůsobení dalšímu nemusí být nutně tím nejjednodušším mechanismem – i když funguje.


Přesměrujte výstup pomocí>> namísto>. To vám umožní zkrátit soubor, aniž by se soubor zvětšil zpět do své původní velikosti. Také nezapomeňte přesměrovat STDERR (2>&1).

Takže konečný výsledek by byl:myprogram >> myprogram.log 2>&1 &


Linux
  1. Základy oprávnění k souborům Linux

  2. Linux – všechno je soubor?

  3. Je používání Rsync během aktualizace zdroje bezpečné?

  1. Jak přesunout soubor v Linuxu

  2. Vysvětlení oprávnění souborů v systému Linux

  3. Proč se v Linuxu používá select

  1. Linux Tail Command

  2. Linux Touch Command

  3. Cat Command v Linuxu