6

在 OSX 10.8 中,输出到 stdout 和 stderr 不再以 Console.app 结尾。我想在不使用 NSLog 的情况下在 Console.app 中获得输出,因为我需要支持使用基本打印语句来打印调试信息的代码(有关一些背景信息,请参阅https://bitbucket.org/ronaldoussoren/py2app/issue/77)。

NSLog 输出“以某种方式”出现在 ASL(Apple 系统日志)日志中,因为您可以使用“syslog -C”查看这些日志行。这就是我尝试将此代码添加到我的应用程序的原因:

aslclient c = asl_open("py2app", "com.apple.console", ASL_OPT_NO_DELAY);
int fd = dup(2);
asl_set_filter(c, ASL_FILTER_MASK_UPTO(ASL_LEVEL_DEBUG));
asl_add_log_file(c, fd);
asl_log(c, NULL, ASL_LEVEL_INFO, "Hello world from py2app launcher");
asl_log_descriptor(c, NULL, ASL_LEVEL_INFO, 1, ASL_LOG_DESCRIPTOR_WRITE);
asl_log_descriptor(c, NULL, ASL_LEVEL_INFO, 2, ASL_LOG_DESCRIPTOR_WRITE);

这有点工作:当我将行写入标准输出流时,这些行被 ASL 转换:输出现在以通常的日志记录前缀为前缀:

Nov 20 13:46:14 Gondolin.local py2app[43722] <Info>: Hello world from py2app launcher

但是,日志文件不会最终出现在 ASL 数据存储区或 Console.app 中。

有谁知道我做错了什么?

4

2 回答 2

2

以下 C 代码似乎可以满足我的要求:

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

static void
setup_logging(void)
{
        aslmsg msg;
        aslclient c = asl_open("py2app", "com.apple.console", 0);

        msg = asl_new(ASL_TYPE_MSG);
        asl_set(msg, ASL_KEY_FACILITY, "com.apple.console");
        asl_set(msg, ASL_KEY_LEVEL, ASL_STRING_NOTICE);
        asl_set(msg, ASL_KEY_READ_UID, "-1");

        int fd = dup(2);
        //asl_set_filter(c, ASL_FILTER_MASK_UPTO(ASL_LEVEL_DEBUG));
        asl_add_log_file(c, fd);
        asl_log(c, NULL, ASL_LEVEL_INFO, "Hello world from py2app launcher");
        asl_log_descriptor(c, msg, ASL_LEVEL_INFO, 1,  ASL_LOG_DESCRIPTOR_WRITE);
        asl_log_descriptor(c, msg, ASL_LEVEL_INFO, 2, ASL_LOG_DESCRIPTOR_WRITE);
}

int main(void)
{
        setup_logging();
        printf("hello world, this is a printf\n");
}

与我的第一次尝试相比,这包含一个更改:它使用 asl_log_descriptor 的“aslmsg”参数显式设置 ASL 设施、级别和 ReadUID。如果没有这些参数,消息将不会出现在 Console.app 中。尤其需要 ReadUID 才能在没有超级用户权限的情况下读取日志条目。

注意:为了方便测试,您可以使用“syslog -C | tail”来读取控制台日志。如果没有 ReadUID,我的程序输出仅在我使用“sudo syslog -C”时可见。

于 2013-05-13T17:02:06.427 回答
1

无需执行 asl_add_log_file(c, dup(2))。

此外,您可以在调用 asl_log_descriptor 而不是在 asl_msg 中设置日志级别。请注意,在信息级别时您没有在 syslog 中看到消息的原因是默认情况下会过滤掉未通知的消息(请参阅 /etc/asl.conf)。

例子:

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

int main() {
    asl_log_descriptor(NULL, NULL, ASL_LEVEL_INFO, STDOUT_FILENO, ASL_LOG_DESCRIPTOR_WRITE);
    asl_log_descriptor(NULL, NULL, ASL_LEVEL_NOTICE, STDERR_FILENO, ASL_LOG_DESCRIPTOR_WRITE);
    fprintf(stdout, "This is written to stdout which will be at log level info.");
    fprintf(stderr, "This is written to stderr which will be at log level notice.");
    return 0;
}
于 2014-09-10T06:35:56.153 回答