【发布时间】:2017-11-07 10:35:45
【问题描述】:
我有一个简单的 C# 程序,其 log4net 配置如下:
<log4net>
<appender name="stdout" type="log4net.Appender.ConsoleAppender">
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%%-5level - %message%newline" />
</layout>
</appender>
<root>
<level value="DEBUG" />
<appender-ref ref="stdout" />
</root>
</log4net>
以及以下代码(为清楚起见而缩写):
public static void Main(String[] args)
{
var log = LogManager.GetLogger("Logger");
log.Info("Hello From Logger");
Console.WriteLine("Hello From Console");
}
我正在 Ubuntu 16.04 系统上使用 .NET 4.5 mono 编译和运行它。当我使用控制台运行程序时,输出如预期:
$ mono Program.exe
INFO - Hello From Logger
Hello From Console
但是,当我在 Docker 容器中以分离模式(即“docker run -d”)运行相同的程序然后检查日志时,我只能从 Console.WriteLine 获取日志:
$ docker logs <container_id>
Hello From Console
在尝试追踪此问题时,我尝试使用守护程序工具 (more info here) 运行程序,它说明了相同的行为,让我相信这是 log4net 而不是 docker 的问题。 我还为 log4net 编写了一个仅执行 Console.Write 的自定义附加程序(我相信这与 ConsoleAppender 的功能相同,但我想消除任何其他可能的变量):
public class CustomAppender: AppenderSkeleton
{
protected override void Append(LoggingEvent loggingEvent)
{
Console.Write(RenderLoggingEvent(loggingEvent));
}
}
但没有运气。 任何对 log4net 有深入了解的人都可以指出我可能做错了什么,或者解释 log4net 可以对 stdout 做什么,以便其他应该捕获该流的程序不会?
更新:情节变厚了!我编写了一个快速而肮脏的可执行文件,它使用 Process 类来执行我的示例程序。然后它从示例程序中获取标准输出并使用 Console.WriteLine 将其写入,如下所示:
Process proc = new Process();
proc.StartInfo.FileName = "/path/to/example.exe";
proc.StartInfo.UseShellExecute = false;
proc.StartInto.RedirectStandardOutput = true;
proc.Start();
Thread.Sleep(1000);
Console.WriteLine(proc.StandardOutput.ReadToEnd());
当我直接从控制台运行它时效果很好,但是当我从 docker / daemonize 运行它时会出现同样的问题。所以现在我真的很困惑。
【问题讨论】:
标签: c# docker mono log4net stdout