admin管理员组

文章数量:1416651

ASP.NET Core 9 MVC controller reads Debian 12 journal using:

  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) };
  }

This code throws exception:

journalctl exit code is 1 and file.Length is 0

I tried to read standard error as shown in comment using:

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

but this throws

System.InvalidOperationException: StandardError has not been redirected.

How to read Linux journal in Debian 12 in an ASP.NET Core 9 MVC controller?

ASP.NET Core 9 MVC controller reads Debian 12 journal using:

  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) };
  }

This code throws exception:

journalctl exit code is 1 and file.Length is 0

I tried to read standard error as shown in comment using:

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

but this throws

System.InvalidOperationException: StandardError has not been redirected.

How to read Linux journal in Debian 12 in an ASP.NET Core 9 MVC controller?

Share Improve this question edited Feb 3 at 5:07 marc_s 757k184 gold badges1.4k silver badges1.5k bronze badges asked Feb 2 at 22:04 AndrusAndrus 28k67 gold badges215 silver badges396 bronze badges 6
  • Not an answer to your question, but it seems you're just trying to read a file, there are better ways to do that than process. – gilliduck Commented Feb 2 at 22:21
  • journal is in binary file or in multiple files. journalctl extracts readable text from those files. There are no packages in .NET which can directly read journal files. syslog-ng can create text files from it but those files are rotated, gzipped and each log has different file. I'm looking for a way to query journal directly without creating text files from it. – Andrus Commented Feb 2 at 22:36
  • Not sure if it's a duplicate because you're on Linux, but here is a similar question with lots of answers, maybe it can help: stackoverflow/q/4291912/1220550 – Peter B Commented Feb 2 at 23:08
  • Maybe p is closed after WaitForExit(), causing p.StandardError to be inaccessible. – Jason Commented Feb 3 at 3:02
  • 1 Please try to modify the code like this gist link, it works for me. Please let me know if it works for you. – Jason Commented Feb 3 at 3:03
 |  Show 1 more comment

1 Answer 1

Reset to default 1

p is closed after WaitForExit(), causing p.StandardError to be inaccessible.

So we can modify the code like below.

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();
}

It works for me.

本文标签: cHow to read journal in LinuxStack Overflow