如何在Linux中将linux syslog映射到printf

Mik*_*ike 4 c linux macros syslog

我在桌面上运行了一个linux应用程序,我想将syslog()调用重定向到printf()调用.

注:希望更换电话,只是重定向

所以我写了一些代码来做到这一点:

#ifndef EMBED
#define syslog(level, stuff) printf("SYSLOG: %s\n", stuff)
#endif
Run Code Online (Sandbox Code Playgroud)

在我使用它的一个文件中工作得很好.我将其移动到一个新文件并收到错误:

error: macro "syslog" passed 3 arguments, but takes just 2
Run Code Online (Sandbox Code Playgroud)

我知道错误是因为新文件中的调用是混合的,有些是使用2个参数连接到syslog,有些是使用3.我也知道我需要以某种方式通过变量参数列表重定向这个,但我该怎么做?我还没有工作呢......

据我了解,syslog()和printf()应该是:

void syslog(int priority, const char *format, ...)
int printf(const char *format, ...)
Run Code Online (Sandbox Code Playgroud)

所以我尝试过:

#define ERR 3
#ifndef EMBED         // This is not defined in my env, btw
#define syslog(pri, fmt, ...) printf(fmt, ...)
#endif
...
void main() {
...
syslog(ERR, "test");
Run Code Online (Sandbox Code Playgroud)

但是这给出了错误:

error: expected expression before ‘...’ token
Run Code Online (Sandbox Code Playgroud)

关于如何使用这个宏的建议?

Jon*_*ler 10

GCC在这方面有一个扩展,但最便携的处理方式是:

#define syslog(priority, ...)    printf(__VA_ARGS__)
Run Code Online (Sandbox Code Playgroud)

优先级是强制性的,但宏扩展会忽略.其余参数(强制格式加上可选的后续参数)__VA_ARGS__在参数列表中使用printf().无论格式字符串是常量(文字)还是变量,都可以.


如果你想将输出标记为代理syslog(),我会调用除了printf()完成工作之外的函数:

#define syslog(priority, ...) syslog_print(__VA_ARGS__)
Run Code Online (Sandbox Code Playgroud)

甚至

#define syslog(priority, ...) syslog_print(__FILE__, __LINE__, __func__, __VA_ARGS__)
Run Code Online (Sandbox Code Playgroud)

这些将被声明为:

extern void syslog_printf(const char *fmt, ...);
Run Code Online (Sandbox Code Playgroud)

要么:

extern void syslog_printf(const char *file, int line, const char *func,
                          const char *fmt, ...);
Run Code Online (Sandbox Code Playgroud)

实现是宏的直接应用<stdarg.h>加上v*printf()函数:

void syslog_printf(const char *file, int line, const char *func,
                   const char *fmt, ...)
{
    va_list args;
    printf("SYSLOG:%s:%d:%s: ", file, line, func);
    va_start(args, fmt);
    vprintf(fmt, args);
    va_end(args);
}
Run Code Online (Sandbox Code Playgroud)

您可以添加时间戳以及您喜欢的任何其他内容; 你也可以很容易地安排输出转到文件而不是标准输出; 您也可以安排在功能内打开或关闭它.因此,平均而言,我会替换syslog()为允许您调整代码使用设施的代理.

事实上,既然你已经发现了改变日志记录行为的要求,我建议syslog()你不要直接在你的代码中使用,而应该使用自己的函数(例如syslog_printf(),但可能使用不同的名称)代码,并具有该功能的各种实现.这样做的唯一不利之处在于,syslog()现在更难以称之为真实- 没有vsyslog()AFAIK.因此,基本调用syslog()将通过在syslog_printf()使用中格式化字符串来完成vsnprintf()(或者vasprintf()如果您可以使用它并且内存耗尽不是可能的问题),然后syslog()使用预格式化的字符串(syslog(priority, "%s", buffer);)调用.当然,您还希望将优先级传递给代理函数以进行中继syslog().

  • 这会是你提到的[vsyslog()](http://docs.oracle.com/cd/E19683-01/816-0213/6m6ne38fl/index.html)吗? (2认同)