在使用 System.Diagnostics.Process(在 Linux 系统上)时,我遇到了一个奇怪的问题。
每次启动一个进程时,会输出 ANSI 转义序列。
这个序列是 <ESC>[?1h<ESC>=
(DECCKM, DECKPAM), 但它并不是被调用的程序产生的,我在这里使用了 pwd
,但是这个序列也可以由其他任何程序创建。
这个序列似乎是在进程外部生成的,因为标准和错误输出流无法捕获它。
更奇怪的是,只有在启动了 Web 主机之后才会出现这个问题!
我构建了一个简化的代码示例。
using System;
using System.Diagnostics;
using System.Threading;
using Microsoft.Extensions.Hosting;
class Program
{
static int count;
static void Main(string[] args)
{
CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
execTest();
Host.CreateDefaultBuilder().Build().RunAsync(cancellationTokenSource.Token);
Thread.Sleep(2000);
execTest();
cancellationTokenSource.Cancel();
Thread.Sleep(2000);
execTest();
}
private static void execTest()
{
for (var i = 0; i < 3; i++)
{
executeCommand("pwd");
Console.WriteLine($"Exectest {++count}");
}
}
static void executeCommand(string cmd)
{
var process = new Process();
process.StartInfo.FileName = cmd;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardError = true;
process.Start();
process.WaitForExit();
}
}
要查看效果,您需要特殊的日志记录、管道或重定向来禁用该效果。
而当xterm解释它们时,转义序列是不可见的。
因此,我使用 script -c myTestProg output.log; cat -A output.log
在输出中,您可以看到前三个ExecuteTests按预期工作,但Exectest 4到9产生了这种意外的输出。
Exectest 1
Exectest 2
Exectest 3
^[[?1h^[=^[[40m^[[32minfo^[[39m^[[22m^[[49m: Microsoft.Hosting.Lifetime[0]
Application started. Press Ctrl+C to shut down.
^[[40m^[[32minfo^[[39m^[[22m^[[49m: Microsoft.Hosting.Lifetime[0]
Hosting environment: Production
^[[40m^[[32minfo^[[39m^[[22m^[[49m: Microsoft.Hosting.Lifetime[0]
Content root path: /home/jeb/xx/csharp-test
^[[?1h^[=Exectest 4
^[[?1h^[=Exectest 5
^[[?1h^[=Exectest 6
^[[40m^[[32minfo^[[39m^[[22m^[[49m: Microsoft.Hosting.Lifetime[0]
Application is shutting down...
^[[?1h^[=Exectest 7
^[[?1h^[=Exectest 8
^[[?1h^[=Exectest 9
我的主要问题是我的程序使用Microsoft.Hosting并每秒调用一个进程,导致我的日志文件被淹没。 即使我禁用了主机的输出日志记录,问题仍然存在。
.ConfigureLogging(loggingBuilder =>
{
loggingBuilder.ClearProviders();
});
问题仍然存在。
什么导致了输出,如何避免或抑制它? System.Diagnostics.Process和Microsoft.Extensions.Hosting之间有什么关系?
PS:这个序列是在Process.Start()之后和调用程序结束之前产生的,在调用WaitForExit之前进行了一些Thread.Sleep(100)的测试。
Microsoft.Hosting.Lifetime
的info
是绿色的,但是^[[?1h
似乎是 DECCKM - 启用光标键应用模式,而^[=
是DECKPAM - 启用键盘应用模式
,但为什么它会被WaitForExit()
产生呢? - jebappsettings.json
中将Logging.Console.DisableColors
设置为true
来禁用颜色吗?请参考这个问题 Logs include control characters (in place of coloring) in Visual Studio output window when using Docker 和这个 PR Add DisableColors option (#764)。或者,使用环境变量ASPNETCORE_LOGGING__CONSOLE__DISABLECOLORS
可以禁用 ANSI 转义字符。 - Christos Lytras