.NET跨平台实践:.NetCore、.Net5/6 Linux守护进程设计
几年前,我写过两篇关于用C#开发Linux守护进程的技术文章,分别是《.NET跨平台实践:用C#开发Linux守护进程》和《.NET跨平台实践:再谈用C#开发Linux守护进程 — 完整篇》。由于当时.net core还很稚嫩,没有在业界得到广泛使用,所以之前这两篇文章的技术是针对Linux+Mono这个环境而言的。现在,.Net Core、.Net5已经大行其道,.Net6也很快就会发行正式版,因此,很有必要再加一篇,阐述一下怎么让.net core以及.net5以上版本的.net程序也能在Linux环境下,以自身的能力成为货真价实的Linux守护进程,而不是借用第三方工具!
这就是本文的初衷。
关于Linux Daemon程序的原理之类的,已经在之前的两篇文章中得到了一些体现,因此,本文就直接上代码,不在高大上的理论中去兜圈子了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 | using System.Threading; using System.Timers; using System.Runtime.InteropServices; using System.IO; using System.Text; /************************************************ * .Net Core/.Net5+ Linux Daemon示例,作者宇内流云 * ************************************************/ namespace daemon { class Program { static unsafe void Main( string [] args) { // 进入守护状态 int pid = fork(); if (pid != 0) exit(0); setsid(); pid = fork(); if (pid != 0) exit(0); umask(0); // 关闭所有打开的文件描述符 int fd_nul = open( "/dev/null" , 0); for ( var i = 0; i <= fd_nul; i++) { if (i < 3) dup2(fd_nul, i); else close(i); } // 进入主方法 //(本示例的功能很简单,就是定时向某个文件写入点内容) DaemonMain(args); } /// <summary> /// Daemon工作状态的主方法 /// </summary> /// <param name="aargs"></param> static void DaemonMain( string [] aargs) { //启动一个线程去处理一些事情 ( new Thread(DaemonWorkFunct) { IsBackground = true }).Start(); //daemon时,控制台输入、输出流已经关闭 // 因此,请不要再用Console.Write/Read等方法 //阻止daemon进程退出 ( new AutoResetEvent( false )).WaitOne(); } static FileStream fs; static int count = 0; static void DaemonWorkFunct() { try { fs = File.Open(Path.Combine( "/tmp" , "daemon.txt" ), FileMode.OpenOrCreate); } catch { exit(1); return ; } var t = new System.Timers.Timer() { Interval = 1000 }; t.Elapsed += OnElapsed; t.Start(); } private static void OnElapsed( object sender, ElapsedEventArgs e) { var s = DateTime.Now.ToString( "yyy-MM-dd HH:mm:ss" ) + "\n" ; var b = Encoding.ASCII.GetBytes(s); fs.Write(b, 0, b.Length); fs.Flush(); count++; if (count > 100) { fs.Close(); fs.Dispose(); exit(0); } } [DllImport( "libc" , SetLastError = true )] static extern int fork(); [DllImport( "libc" , SetLastError = true )] static extern int setsid(); [DllImport( "libc" , SetLastError = true )] static extern int umask( int mask); [DllImport( "libc" , SetLastError = true )] static extern int open([MarshalAs(UnmanagedType.LPStr)] string pathname, int flags); [DllImport( "libc" , SetLastError = true )] static extern int close( int fd); [DllImport( "libc" , SetLastError = true )] static extern int exit( int code); [DllImport( "libc" , SetLastError = true )] static extern int dup2( int oldfd, int newfd); } } |
以上代码就是Linux环境中,.NetCore或.Net5以上版本的.net程序,以纯代码方式使自身成为标准的Linux守护进程的示例代码,你完全可以将它关键部分借用到自己的真实项目中。使用中如果有什么问题或建议,请加入本人的QQ群作进一步交流。
版权声明:本文是 宇内流云 (邮箱:j66x@163.com)原创作品,用c#开发原生的Linux守护进程相关技术及代码亦属本人首发。如需网络转载,请注明出处和作者;没有得到本人书面授权,本人发布于网络的任何关键代码不得被任何团体或个人以任何名义使用到出版物中。
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· .NET Core 托管堆内存泄露/CPU异常的常见思路
· DeepSeek “源神”启动!「GitHub 热点速览」
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)
· DeepSeek R1 简明指南:架构、训练、本地部署及硬件要求
· NetPad:一个.NET开源、跨平台的C#编辑器