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

Linux环境下自动重建并重启.NET控制台应用的问题解决

.NET控制台应用Linux环境自动重启问题解决

问题场景

在Windows开发小型.NET控制台Web服务器,部署到Amazon Linux服务器,通过GitHub Webhook触发自动拉取代码(已实现GitApi类执行git pull),后续编写Restarter类执行dotnet run实现自动重建重启,但在Linux环境下存在以下问题:

  • 主进程退出后,新启动的dotnet run进程脱离当前终端控制组
  • 无法通过Ctrl+C终止进程,只能通过端口查找并使用kill命令终止

现有代码

GitApi 类(自动拉取代码)

using System.Diagnostics;

public static class GitApi
{
    public static void Pull(string path)
    {
        Process process = new Process()
        {
            StartInfo = new ProcessStartInfo()
                {
                FileName = "git",
                Arguments = "pull",
                UseShellExecute = false,
                RedirectStandardOutput = true,
                WorkingDirectory = path
            }
        };
        process.Start();
    }
}

Restarter 类(尝试自动重启)

using System.Diagnostics;

public static class Restarter
{
    public static void Restart(string path)
    {
        Process process = new Process()
        {
            StartInfo = new ProcessStartInfo()
            {
                FileName = "dotnet",
                Arguments = "run",
                UseShellExecute = false,
                WorkingDirectory = path
            }
        };
        process.Start();
        Environment.Exit(0);
    }
}

解决方案

方案1:修复子进程终端关联问题

Linux下父进程退出时,子进程会被init进程接管并脱离当前终端控制组。可以通过exec命令让子进程替换父进程的shell,从而继承终端控制组,实现Ctrl+C可终止:

修改Restarter类代码:

using System.Diagnostics;

public static class Restarter
{
    public static void Restart(string path)
    {
        // 通过bash执行exec命令,让dotnet进程替换shell进程,继承终端控制组
        var startInfo = new ProcessStartInfo()
        {
            FileName = "/bin/bash",
            Arguments = $"-c \"cd {path} && exec dotnet run\"",
            UseShellExecute = false,
            WorkingDirectory = path
        };

        Process.Start(startInfo);
        Environment.Exit(0);
    }
}

方案2:使用systemd管理服务(生产环境推荐)

通过systemd托管.NET应用,是Linux生产环境下更可靠的进程管理方案,支持自动重启、日志收集、便捷的启停命令,完全规避终端关联问题:

  1. 创建systemd服务文件
    在/etc/systemd/system/目录下创建your-app.service(替换为你的应用名称):
[Unit]
Description=你的.NET控制台Web服务器
After=network.target

[Service]
Type=simple
User=ec2-user  # 替换为运行应用的用户
WorkingDirectory=/path/to/your/app  # 替换为应用根目录
ExecStart=/usr/bin/dotnet run
Restart=on-failure  # 进程崩溃时自动重启
RestartSec=5  # 重启间隔5秒

[Install]
WantedBy=multi-user.target
  1. 启用并启动服务
    执行以下命令:
sudo systemctl daemon-reload
sudo systemctl enable your-app.service
sudo systemctl start your-app.service
  1. 修改Webhook重启逻辑
    将Restarter类改为调用systemd重启命令:
using System.Diagnostics;

public static class Restarter
{
    public static void Restart()
    {
        var process = new Process()
        {
            StartInfo = new ProcessStartInfo()
            {
                FileName = "sudo",
                Arguments = "systemctl restart your-app.service",
                UseShellExecute = false,
                RedirectStandardOutput = true
            }
        };
        process.Start();
        process.WaitForExit(); // 等待命令执行完成
    }
}
  1. 配置sudo免密权限
    为运行Webhook服务的用户配置免密执行systemctl命令,避免输入密码:
    执行sudo visudo,添加以下内容:
ec2-user ALL=(ALL) NOPASSWD: /usr/bin/systemctl restart your-app.service

(替换ec2-user为你的用户,your-app.service为服务名称)

额外注意事项

  • 确保运行Webhook服务的用户拥有git pull的权限(可配置SSH密钥免密拉取)
  • 使用dotnet run仅适合开发/测试环境,生产环境建议先发布应用(dotnet publish),然后运行发布后的可执行文件,修改systemd的ExecStart路径为发布后的文件路径

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 10:54:21