Process.Start不会将消息重定向到docker托管的父上下文?

问题描述 投票:2回答:1

这个问题花了我一天的时间,我起初觉得这很简单。

我有一台安装了Docker桌面的主机(Windows 10)。从主机,我想使用docker run启动一个容器,其中包含一些简单的代码来运行。

这是代码(在容器中构建),这是一个.NET核心控制台应用程序(假设它的内置名称是console.dll):

static void Main(string[] args)
{
    Console.WriteLine("Running...");
    _execTest();
    Console.WriteLine("Finished!");
    Console.ReadLine();
}
static void _execTest()
{
    var sharedFilePath = Path.Combine(Environment.CurrentDirectory, "Temp", "test.exe");
    var si = new ProcessStartInfo(sharedFilePath);

    si.RedirectStandardOutput = false;
    si.RedirectStandardError = false;
    si.RedirectStandardInput = false;

    Console.WriteLine("Starting ..." + sharedFilePath);
    var p = Process.Start(si);
    p.WaitForExit();
}

主要代码是启动另一个名为test.exe的程序。该程序放在共享文件夹Temp(通过在主机和容器之间安装文件夹来调用docker run时建立)。

这是test.exe的代码(它只是一个.NET控制台应用程序):

static void Main(string[] args)
{                        
    Console.WriteLine("Something went wrong!");
    Console.Write("Welldone!");    
}

因此,我希望使用test.exeConsole中编写的所有消息都应该返回到父上下文(应该使用相同的STDOUT)。

我已经通过使用dotnet console.dll直接运行容器代码测试了代码,我可以看到预期打印的消息(来自test.exe)。

然而,在将console.dll部署到映像(console)并尝试以下命令来运行容器之后:

docker run --rm -v D:\SourceFolder:C:\app\Temp console

然后不打印消息(来自test.exe)。仅打印直接在父上下文中编写的消息(Running...Starting...Finished!)。

您可以看到上面的命令使用-v将容器中的文件夹C:\app\Temp挂载到主机中的源文件夹D:\SourceFolder。并且test.exe被放入D:\SourceFolder。我确信容器的代码可以通过共享文件夹访问此文件。

这太奇怪了,难以诊断。如果不在容器和主机之间来回共享消息,那么像这样运行docker就没用了。

我希望这里有人可以给我一些建议,以便我可以尝试解决这个问题。谢谢!

更新:如果我使用带有cmd.exe参数的/?(已经存在于docker图像中),那么我可以看到它的输出。所以看起来这是执行EXE共享文件夹的一些问题。

但是,我已经尝试将共享文件首先复制到容器的某个本地文件夹,然后运行该文件但仍然是同一个问题。所以看起来它可能是test.exe文件本身的问题?太荒谬了。

更新:感谢@jazzdelightsme关于检查ExitCode的有用建议,所以实际上容器中的环境缺少一些无法正确启动test.exe的东西。我已经尝试编译针对最低.NET Framework版本2.0的test.exe,但仍然是同样的错误。这是Dockerfile的内容,它应该提供有关容器环境的一些信息:

FROM microsoft/dotnet:2.1-runtime-nanoserver-1709 AS base
WORKDIR /app

FROM microsoft/dotnet:2.1-sdk-nanoserver-1709 AS build
WORKDIR /src
COPY ConsoleApp/ConsoleApp.csproj ConsoleApp/
RUN dotnet restore ConsoleApp/ConsoleApp.csproj
COPY . .
WORKDIR /src/ConsoleApp
RUN dotnet build ConsoleApp.csproj -c Release -o /app

FROM build AS publish
RUN dotnet publish ConsoleApp.csproj -c Release -o /app

FROM base AS final
WORKDIR /app
COPY --from=publish /app .
ENTRYPOINT ["dotnet", "ConsoleApp.dll"]
c# windows docker stdout docker-container
1个回答
1
投票

要检查的一般故障排除事项是流程的退出代码。这通常会给出问题所在的线索。

在这种情况下,退出代码是STATUS_DLL_NOT_FOUND。如果您了解应用程序的依赖关系,仅此一点就足够了,因为您只需手动检查容器并找出丢失的内容即可。

如果您不知道缺少什么,直接调试方法是使用Windows调试器并启用“Show Loader Snaps”。有关获取Windows调试器here的信息。您可以将它们复制到容器中。你可以使用像C:\Debuggers\cdb.exe -xe "ld ntdll" test.exe这样的命令行,它在调试器下启动test.exe,加载ntdll.dll后会立即停止(比正常情况更早)。一旦它停止,你运行!gflag +sls打开加载器快照,然后运行g继续执行。检查喷射应告诉您缺少或未加载的内容。

在这种特殊情况下,STATUS_DLL_NOT_FOUND可能是因为test.exe是.NET Framework应用程序,但是纳米服务器映像中不存在完整的.NET Framework。

© www.soinside.com 2019 - 2024. All rights reserved.