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

Linux下如何检测已执行的.NET控制台应用进程是否运行?

解决Linux下DotNet控制台应用唯一性检测的可行方案

针对Linux下所有dotnet进程名称一致,无法通过进程名判断目标应用是否运行的问题,以下是几个无竞态、跨平台的可靠方案:

方案1:通过进程命令行参数识别

Linux下dotnet进程的命令行参数会包含目标应用的关键标识(比如dotnet run时的项目名,或直接运行dll时的文件路径)。你可以遍历所有dotnet进程,检查其命令行是否包含目标应用的唯一名称(如Bookstore.SendSignUpEmails)。

实现示例(C#):

using System.Diagnostics;
using System.IO;

bool IsAppRunning(string appIdentifier)
{
    var dotnetProcesses = Process.GetProcessesByName("dotnet");
    foreach (var process in dotnetProcesses)
    {
        try
        {
            // Linux下读取/proc/{pid}/cmdline获取完整命令行(进程参数以\0分隔)
            var cmdline = File.ReadAllText($"/proc/{process.Id}/cmdline").Replace('\0', ' ');
            if (cmdline.Contains(appIdentifier))
            {
                return true;
            }
        }
        catch (Exception)
        {
            // 无权限访问进程信息时跳过
            continue;
        }
    }
    return false;
}

// 使用方式
if (!IsAppRunning("Bookstore.SendSignUpEmails"))
{
    Process.Start("dotnet", "run Bookstore.SendSignUpEmails");
}

优缺点:无需修改子应用,仅在主应用处理;但依赖命令行参数格式,若子应用启动方式变化(如直接运行dll)需调整匹配逻辑。

方案2:使用命名互斥体(跨平台)

命名互斥体是系统级同步原语,Windows和Linux均支持。每个子应用启动时尝试创建唯一命名的互斥体,若创建失败则说明已有实例运行;主应用通过尝试打开互斥体判断是否存在运行中的实例。

子应用实现:

using System.Threading;

class Program
{
    static void Main(string[] args)
    {
        // 用应用唯一标识作为互斥体名称,Linux下加"Global/"确保全局可见
        using var mutex = new Mutex(true, "Global/Bookstore.SendSignUpEmails_Mutex", out bool createdNew);
        if (!createdNew)
        {
            Console.WriteLine("应用已在运行");
            return;
        }

        // 执行应用核心逻辑
        // ...
    }
}

主应用检测逻辑:

bool IsAppRunning(string appIdentifier)
{
    try
    {
        using var mutex = Mutex.OpenExisting($"Global/{appIdentifier}_Mutex");
        return true;
    }
    catch (WaitHandleCannotBeOpenedException)
    {
        // 互斥体不存在,无实例运行
        return false;
    }
}

// 使用方式
if (!IsAppRunning("Bookstore.SendSignUpEmails"))
{
    Process.Start("dotnet", "run Bookstore.SendSignUpEmails");
}

优缺点:完全避免竞态,跨平台一致性好;需修改每个子应用的启动逻辑,确保互斥体正确创建与释放。

方案3:PID文件+文件独占锁

通过创建PID文件并使用文件独占锁,确保同一时间仅一个实例运行。子应用启动时以独占模式打开PID文件,进程运行期间保持锁定;主应用通过尝试获取文件锁判断是否有实例在运行。

子应用实现:

using System.IO;
using System.Diagnostics;

class Program
{
    static void Main(string[] args)
    {
        // 非root用户可改用用户目录下的路径,避免权限问题
        var pidFilePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), 
                                      ".run", "Bookstore.SendSignUpEmails.pid");
        Directory.CreateDirectory(Path.GetDirectoryName(pidFilePath));
        
        FileStream pidFileStream = null;
        try
        {
            // 以独占模式打开文件,若已被锁定则抛出异常
            pidFileStream = new FileStream(
                pidFilePath,
                FileMode.Create,
                FileAccess.Write,
                FileShare.None);

            // 写入当前进程PID
            using var writer = new StreamWriter(pidFileStream);
            writer.WriteLine(Process.GetCurrentProcess().Id);
            pidFileStream = null; // 交由using管理流的生命周期

            // 执行应用核心逻辑
            // ...
        }
        catch (IOException)
        {
            Console.WriteLine("应用已在运行");
            return;
        }
        finally
        {
            pidFileStream?.Close();
            // 正常退出时删除PID文件
            if (File.Exists(pidFilePath)) File.Delete(pidFilePath);
        }
    }
}

主应用检测逻辑:

bool IsAppRunning(string appIdentifier)
{
    var pidFilePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), 
                                  ".run", $"{appIdentifier}.pid");
    try
    {
        // 尝试以独占模式打开文件,成功则说明无进程持有锁
        using var stream = new FileStream(
            pidFilePath,
            FileMode.Open,
            FileAccess.Read,
            FileShare.None);
        return false;
    }
    catch (IOException)
    {
        // 文件被锁定,说明有进程运行
        return true;
    }
    catch (FileNotFoundException)
    {
        // 文件不存在,无进程运行
        return false;
    }
}

// 使用方式
if (!IsAppRunning("Bookstore.SendSignUpEmails"))
{
    Process.Start("dotnet", "run Bookstore.SendSignUpEmails");
}

优缺点:符合Linux系统传统做法,无需依赖.NET特定API;需处理文件权限问题,进程异常退出时系统会自动释放锁,但PID文件可能残留(不影响检测逻辑)。

内容的提问来源于stack exchange,提问作者Teoman shipahi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 18:25:18