Supervisor 相信对Linux系统很熟的都知道这个软件,基于Python写的一个守护进程软件(实现后台运行)。具体的介绍和使用我就不再赘述了。
使用asp.net core 部署在Linux常用的方法 我们可以用Docker、Jexus 、Supervisor等。具体应该使用哪个,因不同的软件都有各自的优缺点,根据自身应用的场景选择一个即可。
在使用Supervisor 部署asp.net core的时候通常我们只要在supervisord.d 目录中添加对应的配置文件如xxx.ini或xxx.conf。(具体目录位置和配置文件扩展名请根据supervisord.conf来进行配置约束。)
然后在配置文件command 后面写上dotnet /data/web/webapi.dll ,然后通过 supervisorctl start webapi 即可启动我们的web程序在后台运行。
当我们在DotNet Core中写一个后台程序,比如定时任务程序、MQ的消费者程序等。这样就没必要写成Web程序;在windows里我们可以写一个windows服务程序,直接在后台运行。但是DotNet Core我们只能写控制台程序了。
普通的控制台程序我们写好后放到Linux上直接运行没问题,但是如果使用supervisor 进行部署实现后台进程守护(部署方式同asp.net core一样),会发现 怎么也启动不了。
比如这样一个程序
Linux上直接运行(前台方式),可以完美执行。
使用Supervisord部署添加一个配置文件
使用supervisor运行,会出现错误。
出现错误不能成功运行,如果网上搜索 "supervisor Exited too quickly (process log may have details)”或按照supervisor日志里的错误信息搜索,多数会告诉你目录是否配置错误、目录是否有对应权限、dotnet 命令是否能正常运行等。
我们看看运行日志
这样看是有运行,出现【控制台程序已经启动】多次说明我们的程序被Supervisor 多次重启了,在配置文件中startretries就是启动失败后重启次数。
我们可以通过tail -f /data/logs/apptest.log 查看日志有没有文件有没有继续持续输出我们打印的时间,或者通过ps -efl |grep dotnet 查看当前程序运行的进程是否存在,后者是最准确的。
不难发现我们本次是有运行 因为有启动日志,但是很快进程就会自动退出了。
为控制台程序添加宿主
在asp.net core中我们都知道有个WebHost
asp.net core 中的WebHost
在控制台中我们需要添加HostBuilder来作为宿主。
通过Nuget 添加Microsoft.Extensions.Hosting
修改控制台的Main函数
static async Task Main(string[] args) { Console.WriteLine($"控制台程序已经启动:{DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")}\r\n"); var hostBuilder = new HostBuilder() .ConfigureServices(serviceCollection => { //注册我们的服务接口 serviceCollection.AddSingleton(); }); await hostBuilder.RunConsoleAsync(); }
一般情况Main函数改为异步后变异会报错,会提示找不到合适的静态入口;可以设置语言版本为C#7.1及以上来解决。
我们需要添加一个服务文类用来继承我们的宿主IHostedService接口,并重写服务启动和结束方法。
class MyService : IHostedService { ////// 服务启动 /// /// /// public Task StartAsync(CancellationToken cancellationToken) { return Task.Run(() => { Console.WriteLine("控制台程序已经开启"); //模拟定时需要后台处理的任务 new Task(() => { while (true) { Console.WriteLine("当前时间是:" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")); Thread.Sleep(1000); } }).Start(); }); } /// /// 服务停止 /// /// /// public Task StopAsync(CancellationToken cancellationToken) { return Task.Run(() => { Console.WriteLine("控制台程序已经停止"); }); } }
发布然后使用supervisorctl start apptest 开启看看