GNU/Linux >> Tutoriels Linux >  >> Linux

Tronquer un fichier en cours d'utilisation (Linux)

Depuis coreutils 7.0, il existe un truncate commande.


La chose intéressante à propos de ces fichiers regénérés est que les 128 premiers Ko environ seront tous des zéros après avoir tronqué le fichier en copiant /dev/null au-dessus. Cela se produit parce que le fichier est tronqué à zéro, mais le descripteur de fichier dans l'application pointe toujours immédiatement après sa dernière écriture. Lorsqu'il écrit à nouveau, le système de fichiers traite le début du fichier comme tous les octets zéro - sans réellement écrire les zéros sur le disque.

Idéalement, vous devriez demander au fournisseur de l'application d'ouvrir le fichier journal avec le O_APPEND drapeau. Cela signifie qu'après avoir tronqué le fichier, la prochaine écriture cherchera implicitement jusqu'à la fin du fichier (c'est-à-dire jusqu'au décalage zéro), puis écrira les nouvelles informations.

Ce code truque la sortie standard pour qu'il soit en O_APPEND mode puis invoque la commande donnée par ses arguments (plutôt comme nice exécute une commande après avoir ajusté son nice-level, ou nohup exécute une commande après avoir corrigé les choses pour qu'elle ignore 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);
}

Mes tests ont été quelque peu décontractés, mais à peine suffisants pour me persuader que cela fonctionnait.

Alternative plus simple

Billy note dans sa réponse que '>> ' est l'opérateur d'ajout - et en effet, sur Solaris 10, bash (version 3.00.16(1)) utilise le O_APPEND flag - rendant ainsi le code ci-dessus inutile, comme indiqué ("Black JL :" est mon invite sur cette machine) :

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:

Utilisez la redirection d'ajout plutôt que le code wrapper ("cantrip") ci-dessus. Cela montre simplement que lorsque vous utilisez une technique particulière à d'autres fins (valides), l'adapter à une autre n'est pas nécessairement le mécanisme le plus simple - même si cela fonctionne.


Redirigez la sortie en utilisant>> au lieu de>. Cela vous permettra de tronquer le fichier sans que le fichier ne reprenne sa taille d'origine. N'oubliez pas non plus de rediriger STDERR (2>&1).

Donc le résultat final serait :myprogram >> myprogram.log 2>&1 &


Linux
  1. Comment déplacer un fichier sous Linux

  2. Bases des autorisations de fichiers Linux

  3. Linux - Tout est un fichier ?

  4. L'utilisation de Rsync pendant la mise à jour de la source est-elle sûre ?

  5. Pourquoi select est-il utilisé sous Linux

Commande Gunzip sous Linux

Commande Stat sous Linux

Qu'est-ce qu'umask sous Linux ?

Comment créer un lien symbolique vers un fichier sous Linux

Commandes Linux fréquemment utilisées par les administrateurs système Linux - Partie 5

Extraire le fichier tar.gz sous Linux