これらの再成長したファイルの興味深い点は、ファイルをコピー/dev/null
して切り捨てた後、最初の 128 KB 程度がすべてゼロになることです。これは、ファイルが長さ 0 に切り詰められているために発生しますが、アプリケーションのファイル記述子は最後の書き込みの直後を指しています。再度書き込みを行うと、ファイル システムはファイルの先頭をすべてゼロ バイトとして扱いますが、実際にはゼロをディスクに書き込みません。
理想的には、アプリケーションのベンダーにO_APPEND
フラグ付きのログ ファイルを開くように依頼する必要があります。これは、ファイルを切り捨てた後、次の書き込みで暗黙的にファイルの最後までシークし (オフセット ゼロに戻ることを意味します)、新しい情報を書き込むことを意味します。
このコードは、標準出力を調整してO_APPEND
モードにしてから、その引数で指定されたコマンドを呼び出します ( nice
nice レベルを調整した後にnohup
コマンドを実行したり、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);
}
私のテストは幾分カジュアルでしたが、それが機能することを私に納得させるにはかろうじて十分でした.
より簡単な代替手段
Billyは回答の中で、「>>
」は追加演算子であり、実際、Solaris 10 では bash (バージョン 3.00.16(1)) がO_APPEND
フラグを使用しているため、上記のコードが不要になると述べています (「Black JL:」は、このマシンでの私のプロンプトです):
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:
上記のラッパー (' cantrip ') コードではなく追加リダイレクトを使用してください。これは、ある特定の手法を他の (有効な) 目的に使用する場合、それを別の手法に適応させることは、たとえ機能していても、必ずしも最も単純なメカニズムではないことを示しています。