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?
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.