Pada coreutils 7.0, ada truncate
perintah.
Hal yang menarik tentang file yang ditumbuhkan kembali adalah bahwa sekitar 128 KB pertama akan menjadi nol setelah Anda memotong file dengan menyalin /dev/null
lebih dari itu. Hal ini terjadi karena file terpotong menjadi panjang nol, tetapi deskriptor file dalam aplikasi tetap mengarah tepat setelah penulisan terakhirnya. Saat menulis lagi, sistem file memperlakukan awal file sebagai nol byte - tanpa benar-benar menulis nol ke disk.
Idealnya, Anda harus meminta vendor aplikasi untuk membuka file log dengan O_APPEND
bendera. Ini berarti setelah Anda memotong file, penulisan berikutnya akan secara implisit mencari ke akhir file (artinya kembali ke offset nol) dan kemudian menulis informasi baru.
Kode ini memasang output standar sehingga ada di O_APPEND
mode dan kemudian memanggil perintah yang diberikan oleh argumennya (agak seperti nice
menjalankan perintah setelah menyesuaikan level bagusnya, atau nohup
menjalankan perintah setelah memperbaiki sesuatu sehingga mengabaikan 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);
}
Pengujian saya terhadapnya agak biasa saja, tetapi hampir tidak cukup untuk meyakinkan saya bahwa itu berhasil.
Alternatif yang lebih sederhana
Billy mencatat dalam jawabannya bahwa '>>
' adalah operator append - dan memang, pada Solaris 10, bash (versi 3.00.16(1)) menggunakan O_APPEND
flag - sehingga membuat kode di atas tidak diperlukan, seperti yang ditunjukkan ('Black JL:' adalah prompt saya di mesin ini):
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:
Gunakan pengalihan tambahan daripada kode pembungkus ('cantrip') di atas. Ini hanya untuk menunjukkan bahwa ketika Anda menggunakan satu teknik tertentu untuk tujuan (valid) lainnya, mengadaptasinya ke teknik lain belum tentu merupakan mekanisme yang paling sederhana - meskipun berhasil.
Arahkan ulang output menggunakan>> alih-alih>. Ini akan memungkinkan Anda untuk memotong file tanpa file tumbuh kembali ke ukuran aslinya. Juga, jangan lupa untuk mengalihkan STDERR (2>&1).
Jadi hasil akhirnya adalah:myprogram >> myprogram.log 2>&1 &