gpt4 book ai didi

c# - 从 tail -f "follow"捕获标准输出

转载 作者:太空狗 更新时间:2023-10-29 23:34:07 24 4
gpt4 key购买 nike

我正在尝试在跟踪模式下捕获 tail 的输出,它会在检测到文件长度变化时输出文本——这对于在添加行时跟踪日志文件特别有用。出于某种原因,我对 StandardOutput.Read() 的调用一直处于阻塞状态,直到 tail.exe 完全退出。

相关代码示例:

var p = new Process() {
StartInfo = new ProcessStartInfo("tail.exe") {
UseShellExecute = false,
RedirectStandardOutput = true,
Arguments = "-f c:\\test.log"
}
};
p.Start();

// the following thread blocks until the process exits
Task.Factory.StartNew(() => p.StandardOutput.Read());
// main thread wait until child process exits
p.WaitForExit();

我还尝试使用对 OutputDataReceived 事件处理程序的支持,它表现出相同的阻塞行为:

p.OutputDataReceived += (proc, data) => {
if (data != null && data.Data != null) {
Console.WriteLine(data.Data);
}
};
p.BeginOutputReadLine();

围绕调用 StandardOutput.Read(),我确实有更多的代码,但这简化了示例并且仍然表现出不希望的阻塞行为。我还能做些什么来让我的代码在子应用程序退出之前对 StandardOutput 流中数据的可用性使用react?

这可能只是 tail.exe 运行方式的一个怪癖?我使用的是作为 UnxUtils 包的一部分编译的 2.0 版。

更新:这似乎至少部分与 tail.exe 中的怪癖有关。我从 GnuWin32 中获取了二进制文件项目作为 CoreUtils 包的一部分,版本升级到 5.3.0。如果我使用 -f 选项继续执行而不重试,我会在 STDERR 上遇到可怕的“错误文件描述符”问题(很容易忽略)并且进程会立即终止。如果我使用 -F 选项来包括重试,它似乎在收到错误的文件描述符消息并尝试再次打开文件后正常工作。

是否有来自 coreutils 的更新的 win32 版本?我可以尝试 git 存储库吗?

最佳答案

我知道这并不完全是您要问的,但正如 James 在评论中所说,您可以直接在 C# 中执行等效功能,从而避免启动另一个进程。

你可以这样做的一种方法是这样的:

using System;
using System.IO;
using System.Text;
using System.Threading;

public class FollowingTail : IDisposable
{
private readonly Stream _fileStream;
private readonly Timer _timer;

public FollowingTail(FileInfo file,
Encoding encoding,
Action<string> fileChanged)
{

_fileStream = new FileStream(file.FullName,
FileMode.Open,
FileAccess.Read,
FileShare.ReadWrite);

_timer = new Timer(o => CheckForUpdate(encoding, fileChanged),
null,
0,
500);
}

private void CheckForUpdate(Encoding encoding,
Action<string> fileChanged)
{
// Read the tail of the file off
var tail = new StringBuilder();
int read;
var b = new byte[1024];
while ((read = _fileStream.Read(b, 0, b.Length)) > 0)
{
tail.Append(encoding.GetString(b, 0, read));
}

// If we have anything notify the fileChanged callback
// If we do not, make sure we are at the end
if (tail.Length > 0)
{
fileChanged(tail.ToString());
}
else
{
_fileStream.Seek(0, SeekOrigin.End);
}
}

// Not the best implementation if IDisposable but you get the idea
// See http://msdn.microsoft.com/en-us/library/ms244737(v=vs.80).aspx
// for how to do it properly
public void Dispose()
{
_timer.Dispose();
_fileStream.Dispose();
}
}

然后调用例如:

new FollowingTail(new FileInfo(@"C:\test.log"),
Encoding.ASCII,
s =>
{
// Do something with the new stuff here, e.g. print it
Console.Write(s);
});

关于c# - 从 tail -f "follow"捕获标准输出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6740679/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com