A partir de coreutils 7.0, hay un truncate
comando.
Lo interesante de esos archivos regenerados es que los primeros 128 KB serán todos ceros después de truncar el archivo copiando /dev/null
encima de eso. Esto sucede porque el archivo se trunca a la longitud cero, pero el descriptor del archivo en la aplicación aún apunta inmediatamente después de su última escritura. Cuando vuelve a escribir, el sistema de archivos trata el inicio del archivo como cero bytes, sin escribir realmente los ceros en el disco.
Idealmente, debe pedirle al proveedor de la aplicación que abra el archivo de registro con el O_APPEND
bandera. Esto significa que después de truncar el archivo, la siguiente escritura buscará implícitamente hasta el final del archivo (es decir, volverá al desplazamiento cero) y luego escribirá la nueva información.
Este código manipula la salida estándar para que esté en O_APPEND
mode y luego invoca el comando dado por sus argumentos (más bien como nice
ejecuta un comando después de ajustar su nivel agradable, o nohup
ejecuta un comando después de arreglar las cosas, por lo que ignora 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);
}
Mi prueba fue algo casual, pero apenas lo suficiente para convencerme de que funcionaba.
Alternativa más sencilla
Billy anota en su respuesta que '>>
' es el operador de adición y, de hecho, en Solaris 10, bash (versión 3.00.16(1)) utiliza el O_APPEND
bandera - por lo que el código anterior es innecesario, como se muestra ('Black JL:' es mi mensaje en esta máquina):
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:
Utilice la redirección de datos adjuntos en lugar del código contenedor ('cantrip') anterior. Esto solo demuestra que cuando usa una técnica en particular para otros fines (válidos), adaptarla a otra no es necesariamente el mecanismo más simple, aunque funcione.
Redirija la salida usando>> en lugar de>. Esto le permitirá truncar el archivo sin que vuelva a crecer a su tamaño original. Además, no olvide redirigir STDERR (2>&1).
Entonces el resultado final sería:myprogram >> myprogram.log 2>&1 &