You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在C#(Mono环境)中实现tail -f功能及运行对应Bash脚本

在Mono(C#)中实现tail -f功能并处理SFTP日志事件

我来分享两种适配Mono环境的解决方案,既能实现tail -f实时跟踪日志的效果,也能满足你处理包含sftp-server行的需求:

方案一:纯C#实现tail -f逻辑

如果不想依赖Bash脚本,完全用C#代码模拟tail -f的行为是可行的。核心思路是持续监控日志文件的大小变化,当文件新增内容时读取并处理。这种方式更可控,也更贴合.NET/Mono的生态。

以下是完整的实现代码:

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

class TailAuthLog
{
    static void Main(string[] args)
    {
        string logPath = "/var/log/auth.log";
        FileInfo logFile = new FileInfo(logPath);
        long lastFileSize = 0;

        Console.WriteLine($"开始跟踪日志: {logPath}");
        Console.WriteLine("按Ctrl+C停止...");

        try
        {
            while (true)
            {
                logFile.Refresh();
                // 检查文件是否变大(有新内容写入)
                if (logFile.Length > lastFileSize)
                {
                    using (FileStream stream = new FileStream(logPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
                    {
                        // 定位到上次读取的位置
                        stream.Seek(lastFileSize, SeekOrigin.Begin);
                        using (StreamReader reader = new StreamReader(stream, Encoding.UTF8))
                        {
                            string line;
                            // 读取所有新增的行
                            while ((line = reader.ReadLine()) != null)
                            {
                                Console.WriteLine($"新日志行: {line}");
                                // 检查是否包含sftp-server
                                if (line.Contains("sftp-server"))
                                {
                                    // 在这里添加你的处理逻辑
                                    Console.WriteLine("=== 检测到SFTP服务器日志,开始处理 ===");
                                    // 示例:打印该行详情
                                    Console.WriteLine($"处理内容: {line}");
                                    // 可以在这里调用其他业务方法、写入数据库等
                                }
                            }
                        }
                    }
                    // 更新最后读取的文件大小
                    lastFileSize = logFile.Length;
                }
                // 每隔1秒检查一次,避免过度占用CPU
                System.Threading.Thread.Sleep(1000);
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine($"发生错误: {ex.Message}");
        }
    }
}

代码说明:

  • 使用FileInfo监控文件大小变化,替代轮询整个文件的低效方式
  • 通过FileStream的Seek方法定位到上次读取的位置,只读取新增内容
  • 加入FileShare.ReadWrite确保日志文件被系统写入时,我们仍能读取
  • 用Thread.Sleep(1000)降低CPU占用,你可以根据需求调整间隔
  • 当检测到包含sftp-server的行时,直接在代码块中添加你的业务逻辑

编译运行(Mono环境):

mcs TailAuthLog.cs
sudo mono TailAuthLog.exe  # 需要sudo权限读取auth.log

方案二:在Mono中调用现有Bash脚本

如果你想保留已有的Bash脚本逻辑,直接在C#中启动Bash进程执行脚本也是一种简单的方案。这种方式不需要重写代码,适合快速迁移。

第一步:确保你的Bash脚本可执行

先给脚本添加执行权限:

chmod +x your_script.sh

第二步:C#调用脚本的代码实现

using System;
using System.Diagnostics;

class RunBashScript
{
    static void Main(string[] args)
    {
        string scriptPath = "/path/to/your_script.sh"; // 替换为你的脚本路径

        ProcessStartInfo startInfo = new ProcessStartInfo
        {
            FileName = "/bin/bash",
            Arguments = scriptPath,
            UseShellExecute = false,
            RedirectStandardOutput = true,
            RedirectStandardError = true,
            CreateNoWindow = false, // 设为true可以隐藏控制台窗口
            Verb = "runas" // 用于提权,部分环境可能需要
        };

        using (Process process = new Process())
        {
            process.StartInfo = startInfo;
            // 绑定输出和错误事件,实时获取脚本输出
            process.OutputDataReceived += (sender, e) => 
            {
                if (!string.IsNullOrEmpty(e.Data))
                {
                    Console.WriteLine($"脚本输出: {e.Data}");
                }
            };
            process.ErrorDataReceived += (sender, e) => 
            {
                if (!string.IsNullOrEmpty(e.Data))
                {
                    Console.WriteLine($"脚本错误: {e.Data}");
                }
            };

            try
            {
                process.Start();
                process.BeginOutputReadLine();
                process.BeginErrorReadLine();
                process.WaitForExit(); // 等待脚本结束(因为tail -f是持续运行的,所以这里会一直阻塞)
            }
            catch (Exception ex)
            {
                Console.WriteLine($"启动脚本失败: {ex.Message}");
            }
        }
    }
}

注意事项:

  • 读取/var/log/auth.log需要管理员权限,所以运行Mono程序时需要加上sudo
  • 如果你的Bash脚本中需要处理逻辑,直接在原脚本的# ... 对该行进行处理位置添加即可,C#代码会实时捕获脚本的输出
  • 如果不需要捕获脚本输出,可以去掉RedirectStandardOutput和对应的事件绑定

编译运行:

mcs RunBashScript.cs
sudo mono RunBashScript.exe

两种方案各有优劣:纯C#方案更灵活,适合后续扩展.NET生态的功能;调用Bash脚本方案更快捷,适合复用现有逻辑。你可以根据自己的需求选择~

内容的提问来源于stack exchange,提问作者Tono Nam

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 08:36:14