如何制作响应 ubuntu 14.04 和 16.04 上的系统日志事件的 c# 程序?
How to make a c# program that responds to syslog events on ubuntu 14.04 and 16.04?
我的系统日志事件响应解决方案在几个小时后停止工作。我是 运行 'tail -f' 来自 C# 并订阅了 DataReceived 事件。我的问题是,几个小时后它似乎只是停止工作而没有抛出错误或退出进程。我认为当系统日志文件翻转时会发生这种情况。
几个小时后停止工作的当前解决方案:
using System;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
using System.Threading.Tasks.Dataflow;
using App.Configuration;
using App.LogData;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
namespace IQIngest.SrtWatch.Services
{
public class SyslogReaderService
{
private ILogger<SyslogReaderService> _logger;
private CancellationTokenSource _cancellationTokenSource;
private IOptionsSnapshot<AppSettings> _appSettings;
private ITargetBlock<string> _targetQueue;
public SyslogReaderService(ILogger<SyslogReaderService> logger,
CancellationTokenSource cancellationTokenSource,
IOptionsSnapshot<AppSettings> appSettings,
ITargetBlock<string> targetQueue)
{
_logger = logger;
_cancellationTokenSource = cancellationTokenSource;
_appSettings = appSettings;
_targetQueue = targetQueue;
}
public async Task StartReader()
{
ProcessStartInfo startInfo = new ProcessStartInfo($"/usr/bin/tail", $"-f {_appSettings.Value.TailedFile}")
{
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true
};
await Task.Factory.StartNew(() =>
{
try
{
using (Process tail = new Process()
{
StartInfo = startInfo
})
{
_cancellationTokenSource.Token.Register(tail.Kill);
tail.OutputDataReceived += handleLine;
tail.ErrorDataReceived += handleLine;
tail.Start();
_logger.LogDebug($"Started tail process for file {{@{LogFields.FILENAME_STR}}}.", _appSettings.Value.TailedFile);
tail.BeginOutputReadLine();
tail.BeginErrorReadLine();
tail.WaitForExit();
//Stops working and doesn't make it to this line.
_logger.LogDebug($"Tail stopped.");
if (!_cancellationTokenSource.IsCancellationRequested) _cancellationTokenSource.Cancel();
}
}
catch (Exception ex)
{
_logger.LogError(ex, $"Unhandled exception thrown from {nameof(SyslogReaderService)}.");
}
});
}
private void handleLine(object sender, DataReceivedEventArgs e)
{
_logger.LogDebug($"Posting new line to internal processing queue.");
_targetQueue.Post(e.Data);
}
}
}
如果我上面的代码有一个明显的问题可以解决这个问题,那么一个简单的解决方案会很好,但是我认为我可能需要采取不同的方法。
首先声明我对syslog的了解不是很深,但据我了解,您可以配置syslog将事件转发到'syslog server'。所以我想我可以配置 syslog 以将事件发送到本地主机端口并让我的应用程序响应这些事件。有了这个解决方案,我认为我可以绕过拖尾文件的不确定性,并且如果我只是增量读取和评估哪些行是新的,也可以处理文件的滚动。因此,如果我的解决方案没有明显的问题,那么我该如何配置 syslog 以将事件副本发送到我的本地 c# 应用程序 运行?
我最终配置 syslog 以将事件发送到本地 udp 端口,然后在 c# 端监听该端口。拖尾文件不是要走的路。
我的系统日志事件响应解决方案在几个小时后停止工作。我是 运行 'tail -f' 来自 C# 并订阅了 DataReceived 事件。我的问题是,几个小时后它似乎只是停止工作而没有抛出错误或退出进程。我认为当系统日志文件翻转时会发生这种情况。
几个小时后停止工作的当前解决方案:
using System;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
using System.Threading.Tasks.Dataflow;
using App.Configuration;
using App.LogData;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
namespace IQIngest.SrtWatch.Services
{
public class SyslogReaderService
{
private ILogger<SyslogReaderService> _logger;
private CancellationTokenSource _cancellationTokenSource;
private IOptionsSnapshot<AppSettings> _appSettings;
private ITargetBlock<string> _targetQueue;
public SyslogReaderService(ILogger<SyslogReaderService> logger,
CancellationTokenSource cancellationTokenSource,
IOptionsSnapshot<AppSettings> appSettings,
ITargetBlock<string> targetQueue)
{
_logger = logger;
_cancellationTokenSource = cancellationTokenSource;
_appSettings = appSettings;
_targetQueue = targetQueue;
}
public async Task StartReader()
{
ProcessStartInfo startInfo = new ProcessStartInfo($"/usr/bin/tail", $"-f {_appSettings.Value.TailedFile}")
{
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardError = true
};
await Task.Factory.StartNew(() =>
{
try
{
using (Process tail = new Process()
{
StartInfo = startInfo
})
{
_cancellationTokenSource.Token.Register(tail.Kill);
tail.OutputDataReceived += handleLine;
tail.ErrorDataReceived += handleLine;
tail.Start();
_logger.LogDebug($"Started tail process for file {{@{LogFields.FILENAME_STR}}}.", _appSettings.Value.TailedFile);
tail.BeginOutputReadLine();
tail.BeginErrorReadLine();
tail.WaitForExit();
//Stops working and doesn't make it to this line.
_logger.LogDebug($"Tail stopped.");
if (!_cancellationTokenSource.IsCancellationRequested) _cancellationTokenSource.Cancel();
}
}
catch (Exception ex)
{
_logger.LogError(ex, $"Unhandled exception thrown from {nameof(SyslogReaderService)}.");
}
});
}
private void handleLine(object sender, DataReceivedEventArgs e)
{
_logger.LogDebug($"Posting new line to internal processing queue.");
_targetQueue.Post(e.Data);
}
}
}
如果我上面的代码有一个明显的问题可以解决这个问题,那么一个简单的解决方案会很好,但是我认为我可能需要采取不同的方法。
首先声明我对syslog的了解不是很深,但据我了解,您可以配置syslog将事件转发到'syslog server'。所以我想我可以配置 syslog 以将事件发送到本地主机端口并让我的应用程序响应这些事件。有了这个解决方案,我认为我可以绕过拖尾文件的不确定性,并且如果我只是增量读取和评估哪些行是新的,也可以处理文件的滚动。因此,如果我的解决方案没有明显的问题,那么我该如何配置 syslog 以将事件副本发送到我的本地 c# 应用程序 运行?
我最终配置 syslog 以将事件发送到本地 udp 端口,然后在 c# 端监听该端口。拖尾文件不是要走的路。