Skip to content

Instantly share code, notes, and snippets.

@codeyu
Created April 25, 2017 01:54
Show Gist options
  • Save codeyu/629e21653646ca378db0d7a0d54d1497 to your computer and use it in GitHub Desktop.
Save codeyu/629e21653646ca378db0d7a0d54d1497 to your computer and use it in GitHub Desktop.
一个完整的linux daemon示例
using System;
using System.Threading;
using System.Timers;
using System.Runtime.InteropServices;
using System.IO;
using System.Text;
/********************************************
* 一个完整的linux daemon示例,作者宇内流云 *
********************************************/
namespace daemon
{
class Program
{
const string DaemonTag = "--daemon.";
static void Main(string[] args)
{
// 如果已经是daemon后台服务,就直接执行后台主函数
if (string.IsNullOrEmpty(Environment.GetEnvironmentVariable(DaemonTag)) == false)
{
Environment.SetEnvironmentVariable(DaemonTag, null);
DaemonMain(args);
return;
}
// 如果还不是daemon状态,就作daemon处理
///////////////////////////////////////////////
int pid = fork();
if (pid != 0) exit(0);
setsid();
pid = fork();
if (pid != 0) exit(0);
umask(0);
// 这儿已经进入“守护进程”工作状态了!
//关闭所有打开的文件描述符
int max = open("/dev/null", 0);
for (var i = 0; i <= max; i++) { close(i); }
// 设置标记,防止重复运行
Environment.SetEnvironmentVariable(DaemonTag,"yes");
//为execp重组参数
var args1 = args == null ? new string[2] : new string[args.Length + 2];
args1[0] = "mono";
args1[1] = Path.Combine(Environment.CurrentDirectory, Thread.GetDomain().FriendlyName);
//复制参数
if (args1.Length > 2)
{
for (var i = 0; i < args.Length; i++)
{ args1[i + 2] = args[i]; }
}
//守护状态下重新加载和运行本程序
execvp("mono", args1);
}
/// <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() {
fs = File.Open("/tmp/daemon.txt", FileMode.OpenOrCreate);
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 execvp([MarshalAs(UnmanagedType.LPStr)]string file, string[] argv);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment