我有一个闭源遗留应用程序,具有非常有趣的行为:
它使用 N 兆字节的固定大小日志文件,当文件已满时,它将“查找”指针重置为 0 并从头开始覆盖文件而不截断它。 因此,当它增长到 N 兆字节后,您最终会在文件中间看到最后的应用程序日志,并跟踪前一组 N 兆字节的日志...
显然修改应用程序是不可能的,所以我不知道我可以做什么来解决这个问题并能够将这些日志条目导入到系统日志服务器中。 我特别恼火的是当前最新的日志条目不在文件末尾,这对我来说听起来像是一个明确的阻止程序。
我可能在这里看到的选项是:
有什么建议吗?
使用
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
可能不适用于您的应用。
但是你应该能够调整它——想法应该可行。