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 &