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 &