GNU/Linux >> Linux Esercitazione >  >> Linux

Troncare un file mentre è in uso (Linux)

A partire da coreutils 7.0, c'è un truncate comando.


La cosa interessante di quei file ricresciuti è che i primi 128 KB circa saranno tutti zero dopo che avrai troncato il file copiando /dev/null sopra. Ciò accade perché il file viene troncato a lunghezza zero, ma il descrittore di file nell'applicazione punta ancora immediatamente dopo l'ultima scrittura. Quando scrive di nuovo, il file system considera l'inizio del file come tutti zero byte, senza scrivere effettivamente gli zeri sul disco.

Idealmente, dovresti chiedere al fornitore dell'applicazione di aprire il file di registro con O_APPEND bandiera. Ciò significa che dopo aver troncato il file, la scrittura successiva cercherà implicitamente la fine del file (ovvero torna all'offset zero) e quindi scriverà le nuove informazioni.

Questo codice trucca l'output standard in modo che sia in O_APPEND mode e quindi invoca il comando dato dai suoi argomenti (piuttosto come nice esegue un comando dopo aver regolato il suo nice-level, o nohup esegue un comando dopo aver sistemato le cose in modo che ignori 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);
}

Il mio test è stato in qualche modo casuale, ma appena sufficiente per convincermi che funzionava.

Alternativa più semplice

Billy nota nella sua risposta che '>> ' è l'operatore di accodamento - e in effetti, su Solaris 10, bash (versione 3.00.16(1)) usa O_APPEND flag - rendendo così superfluo il codice sopra, come mostrato ('Black JL:' è il mio prompt su questa macchina):

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:

Usa il reindirizzamento di accodamento piuttosto che il codice wrapper ("cantrip") sopra. Questo dimostra che quando usi una particolare tecnica per altri (validi) scopi, adattarla a un altro ancora non è necessariamente il meccanismo più semplice, anche se funziona.


Reindirizza l'output usando>> invece di>. Ciò ti consentirà di troncare il file senza che il file torni alla sua dimensione originale. Inoltre, non dimenticare di reindirizzare STDERR (2>&1).

Quindi il risultato finale sarebbe:myprogram >> myprogram.log 2>&1 &


Linux
  1. Come spostare un file in Linux

  2. Nozioni di base sui permessi dei file Linux

  3. Linux:tutto è un file?

  4. L'uso di Rsync durante l'aggiornamento della sorgente è sicuro?

  5. Perché select è usato in Linux

Comando Gunzip in Linux

Comando Stat in Linux

Cos'è umask in Linux?

Come collegare simbolicamente un file in Linux

Comandi Linux usati frequentemente dagli amministratori di sistema Linux – Parte 5

Estrai il file tar.gz in Linux