从应用程序中提取干净的日志,覆盖其日志文件,而不先在 Linux 上截断它

问题描述 投票:0回答:1

我有一个闭源遗留应用程序,具有非常有趣的行为:

它使用 N 兆字节的固定大小日志文件,当文件已满时,它将“查找”指针重置为 0 并从头开始覆盖文件而不截断它。 因此,当它增长到 N 兆字节后,您最终会在文件中间看到最后的应用程序日志,并跟踪前一组 N 兆字节的日志...

显然修改应用程序是不可能的,所以我不知道我可以做什么来解决这个问题并能够将这些日志条目导入到系统日志服务器中。 我特别恼火的是当前最新的日志条目不在文件末尾,这对我来说听起来像是一个明确的阻止程序。

我可能在这里看到的选项是:

  • 能够以某种方式检测应用程序正在写入的当前偏移量,并按照此跟踪新行,但我不知道该怎么做
  • 使用 LD_PRELOAD 对 C 代码进行脏修补,以确保日志文件永远不会被覆盖或首先完成截断,以便我可以跟踪它。

有什么建议吗?

linux logging syslog ld-preload
1个回答
0
投票

使用

LD_PRELOAD
应该可以。

让我们尝试一个示例(假设我理解您对应用程序行为的解释):

#include <stdio.h>
#include <unistd.h>

const size_t MAX_LOG_SIZE = 1024;

int main()
{
  FILE *fp = fopen("LOG", "w");
  int counter = 0;
  while (1) {
    fprintf(fp, "Log line %8d\n", ++counter);
    fflush(fp);
    if (ftell(fp) > MAX_LOG_SIZE) {
      fprintf(stderr, "Log size exceeded, rewinding\n");
      rewind(fp);
    }
    if ((counter % 10) == 0) {
      fprintf(stderr, "Counter: %d\n", counter);
    }
    usleep(100000);
  }
}
Counter: 10
Counter: 20
Counter: 30
Counter: 40
Counter: 50
Log size exceeded, rewinding
Counter: 60
Counter: 70
^C

LOG
中,我们找到了预期的“乱序”条目:

Log line       58
...
Log line       77
Log line       78
Log line       22
Log line       23
...

现在让我们“修复”应用程序,以便它在倒带之前执行一些代码

LOG

// rewind.c
#define _USE_GNU

#include <dlfcn.h>
#include <stdio.h>

typedef void (*PFN)(FILE *);

void rewind(FILE *fp)
{
  static PFN pfn;
  if (pfn == NULL) pfn = dlsym(RTLD_NEXT, "rewind");

  fprintf(stderr, "saving LOG before rewind\n");
  // insert code to upload the LOG here.
  return pfn(fp);
}
gcc -fPIC -shared -o rewind.so rewind.c
LD_PRELOAD=./rewind.so ./a.out
Counter: 10
Counter: 20
Counter: 30
Counter: 40
Counter: 50
Log size exceeded, rewinding
saving LOG before rewind
Counter: 60
Counter: 70
Counter: 80
Counter: 90
Counter: 100
Counter: 110
Log size exceeded, rewinding
saving LOG before rewind
Counter: 120
Counter: 130
Counter: 140
^C

瞧。

附注如果您的应用使用

rewind.c
而不是
fseek
,或者根本不使用
rewind
,则
stdio
可能不适用于您的应用。

但是你应该能够调整它——想法应该可行。

© www.soinside.com 2019 - 2024. All rights reserved.