简体   繁体   English

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

[英]How can I map linux syslog to printf in C

I have a linux application running on my desk top, and I wanted to redirect the syslog() calls to printf() calls. 我在桌面上运行了一个linux应用程序,我想将syslog()调用重定向到printf()调用。

Note: I do not want to replace the calls, just redirect 注:不想更换电话,只是重定向

So I wrote some code to do this: 所以我写了一些代码来做到这一点:

#ifndef EMBED
#define syslog(level, stuff) printf("SYSLOG: %s\n", stuff)
#endif

Works great in the one file where I was using it. 在我使用它的一个文件中工作得很好。 I moved this to a new file and got an error: 我将其移动到一个新文件并收到错误:

error: macro "syslog" passed 3 arguments, but takes just 2

I know the error is because the calls in the new file are mixed, some are using 2 arguments to syslog, some are using 3. I also know I need to somehow redirect this via variable argument lists, but how exactly do I do this? 我知道错误是因为新文件中的调用是混合的,有些是使用2个参数连接到syslog,有些是使用3.我也知道我需要以某种方式通过变量参数列表重定向,但我该怎么做? I haven't gotten it working yet... 我还没有工作呢......

As I understand it, syslog() and printf() should be: 据我了解,syslog()和printf()应该是:

void syslog(int priority, const char *format, ...)
int printf(const char *format, ...)

So I tried: 所以我尝试过:

#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");

but that gives the error: 但是这给出了错误:

error: expected expression before ‘...’ token

Suggestions on how this macro should look/be used? 关于如何使用这个宏的建议?

GCC has an extension in this area, but the most portable way of handling it is: GCC在这方面有一个扩展,但最便携的处理方式是:

#define syslog(priority, ...)    printf(__VA_ARGS__)

The priority is mandatory, but is ignored by the macro expansion. 优先级是强制性的,但宏扩展会忽略。 The rest of the arguments (the mandatory format plus optional following arguments) are in the __VA_ARGS__ used in the argument list to printf() . 其余参数(强制格式加上可选的后续参数)位于printf()的参数列表中使用的__VA_ARGS__中。 This will be OK whether the format string is a constant (literal) or a variable. 无论格式字符串是常量(文字)还是变量,都可以。


If you want to tag the output as being for the surrogate of syslog() , I'd call a function other than printf() to do the job: 如果你想将输出标记为syslog()的代理,我会调用printf()以外的printf()来完成这项工作:

#define syslog(priority, ...) syslog_print(__VA_ARGS__)

or even 甚至

#define syslog(priority, ...) syslog_print(__FILE__, __LINE__, __func__, __VA_ARGS__)

These would be declared as: 这些将被声明为:

extern void syslog_printf(const char *fmt, ...);

or: 要么:

extern void syslog_printf(const char *file, int line, const char *func,
                          const char *fmt, ...);

The implementation is a straight-forward application of the macros in <stdarg.h> plus the v*printf() functions: 该实现是<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);
}

You can add timestamps and whatever else you like; 您可以添加时间戳以及您喜欢的任何其他内容; you can also rather easily arrange for the output to go to a file instead of standard output; 你也可以很容易地安排输出转到文件而不是标准输出; you can also arrange for it to be turned on or off inside the function. 您也可以安排在功能内打开或关闭它。 So, on average, I would replace syslog() with a surrogate that allows you to tune your codes use of the facilities. 因此,平均而言,我会将syslog()替换为允许您调整代码使用设施的代理。

In fact, since you've uncovered a requirement to change the behaviour of logging, I would suggest that instead of using syslog() directly in your code, you should use your own function (for example, the syslog_printf() , but possibly under a different name) in your code, and have various implementations of that function available to you. 事实上,既然你已经发现了改变日志记录行为的要求,我建议你不要直接在代码中使用syslog() ,而应该使用你自己的函数(例如, syslog_printf() ,但可能在代码中的不同名称,并且可以使用该功能的各种实现。 The only downside to doing so is that calling the real syslog() is now harder — there isn't a vsyslog() AFAIK. 这样做的唯一缺点是调用真正的syslog()现在更难 - 没有vsyslog() AFAIK。 So, the basic call to syslog() would be done by formatting the string in syslog_printf() using vsnprintf() (or vasprintf() if that's available to you and memory exhaustion isn't a likely problem), and then calling syslog() with the preformatted string ( syslog(priority, "%s", buffer); ). 因此,对syslog()的基本调用将通过使用vsnprintf() (或vasprintf()格式化syslog_printf()的字符串来完成,如果您可以使用它并且内存耗尽不是可能的问题),然后调用syslog()使用预格式化的字符串( syslog(priority, "%s", buffer); )。 Of course, you'd also want the priority passed to the surrogate function for relay to syslog() . 当然,您还希望将优先级传递给代理函数以进行中继到syslog()

The fmt string is expected to contain its own formatting specifiers, which are filled in with the variadic arguments. fmt字符串应包含自己的格式说明符,这些说明符用可变参数填充。 First off, you could simply ignore the actual arguments and just print the formatting string. 首先,您可以简单地忽略实际参数,只打印格式化字符串。 You need a variadic macro: 你需要一个可变的宏:

#define syslog(level, fmt, ...) printf("SYSLOG: %s\n", fmt)

Second, if you're willing to take a gigantic risk and expect the user to provide the formatting string as a literal rather than a variable, you can concatenate your own string: 其次,如果您愿意承担巨大的风险并期望用户提供格式字符串作为文字而不是变量,您可以连接自己的字符串:

#define syslog(level, fmt, ...) printf("SYSLOG[%d] " fmt, level, ##__VA_ARGS__)

This will work for syslog(1, "Hello"); 这适用于syslog(1, "Hello"); , but not for syslog(1, str); ,但不适用于syslog(1, str); .

If you don't want to depend on variadic macros (C99 feature), you could also do this: 如果您不想依赖于可变参数宏(C99功能),您也可以这样做:

#define syslog my_syslog

static inline int my_syslog(int prio, const char *fmt, ...)
{
    int r;
    va_list ap;
    va_start(ap, fmt);
    r = vprintf(fmt, ap);
    va_end(ap);
    return r;
}

or similar. 或类似的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM