代码之家  ›  专栏  ›  技术社区  ›  Andrus

如何在Linux中阅读期刊

  •  1
  • Andrus  · 技术社区  · 4 月前

    ASP。NET Core 9 MVC控制器使用以下命令读取Debian 12日志:

      public async Task<IActionResult> Syslog(string param = "-r -u eevatest.service --since \"2 days ago\""
        )
      {
        var p = new Process
        {
          StartInfo = { CreateNoWindow = true,
                        RedirectStandardOutput = true,
                        RedirectStandardError = true,
                        RedirectStandardInput = true,
                        UseShellExecute = false,
                        FileName = "/usr/bin/journalctl"
                    }
        };
    
        p.StartInfo.Arguments = param;
    
        if (!p.Start())
          throw new Exception("journalctl not started");
    
        var buffer = new byte[32768];
        byte[] file;
    
        using (var ms = new MemoryStream())
        {
          while (true)
          {
            Thread.Sleep(10 * 1000);
            var read = await p.StandardOutput.BaseStream.ReadAsync(buffer.AsMemory(0, buffer.Length));
            if (read <= 0)
              break;
            await ms.WriteAsync(buffer.AsMemory(0, read));
          }
          file = ms.ToArray();
        }
    
        if (!p.WaitForExit(60000))
          throw new Exception("journalctl not exited");
    
        var returnCode = p.ExitCode;
        p.Close();
    
        if (returnCode != 0) {
    //Reading standard error throws
    // System.InvalidOperationException: StandardError has not been redirected.
    // var log = await p.StandardError.ReadToEndAsync();
    
          throw new Exception(returnCode  +" journalctl exit error, length "+ file.Length );
    }
    
        return new ContentResult() { Content = Encoding.UTF8.GetString(file) };
      }
    

    此代码引发异常:

    journalctl退出代码为1和file。长度为0

    我试图阅读注释中显示的标准错误,使用:

    var log = await p.StandardError.ReadToEndAsync();
    

    但这抛出

    系统。InvalidOperationException:尚未重定向StandardError。

    如何在ASP.NET中阅读Debian 12中的Linux日志。NET Core 9 MVC控制器?

    0 回复  |  直到 4 月前
        1
  •  1
  •   Jason Pan    4 月前

    p 关闭后 WaitForExit() ,导致 p.StandardError 无法进入。

    所以我们可以像下面这样修改代码。

    public async Task<IActionResult> Syslog(string param = "-r -u eevatest.service --since \"2 days ago\"")
    {
        var p = new Process
        {
            StartInfo = {
                FileName = "/usr/bin/journalctl",
                Arguments = param,
                RedirectStandardOutput = true,
                RedirectStandardError = true,  
                UseShellExecute = false,
                CreateNoWindow = true
            }
        };
    
        try
        {
            p.Start(); 
    
            Task<string> errorTask = p.StandardError.ReadToEndAsync();
            Task<byte[]> outputTask = ReadStreamAsync(p.StandardOutput.BaseStream);
    
            bool exited = await Task.Run(() => p.WaitForExit(60000));
            if (!exited)
                throw new Exception("journalctl did not exit in time");
    
            string errorOutput = await errorTask;
            byte[] output = await outputTask;
    
            if (p.ExitCode != 0)
                throw new Exception($"journalctl exited with code {p.ExitCode}, error: {errorOutput}");
    
            return new ContentResult { Content = Encoding.UTF8.GetString(output) };
        }
        finally
        {
            p.Dispose(); 
        }
    }
    
    private static async Task<byte[]> ReadStreamAsync(Stream stream)
    {
        using var ms = new MemoryStream();
        await stream.CopyToAsync(ms);
        return ms.ToArray();
    }
    

    它对我有效。

    enter image description here