Help us understand the problem. What is going on with this article?

Windows Serverでプロセスをサービス化する(pythonのsupervisorっぽく)

More than 3 years have passed since last update.

Windows Serverで長期間動作し続けるサービスのためにプロセスを監視して落ちたら自動で再起動するServiceの作り方です。
pythonのsupervisorのようなもの。

Serviceの作り方

ServiceBaseを継承し、OnStart()とOnStop()のoverrideにやりたい事を実装するといいようです。
プロセスの起動、落ちてるかの確認と再起動、プロセスの停止を実装してみます。

using System.Diagnostics;
using System.ServiceProcess;
using System.Threading.Tasks;

namespace Suporvisor
{
    class Suporvisor: ServiceBase
    {
        public static void Main()
        {
            var service = new Suporvisor();
            ServiceBase.Run(service);
            return;
        }

        const int checkIntervalMillseconds = 1000;
        const string exePath = @"C:\Supervisor\Program.exe";
        readonly object lockObject = new object();
        Process process;
        Task checker;

        public Suporvisor()
        {
            AutoLog = true;
            CanShutdown = true;
            CanStop = true;
            ServiceName = "Supervisor";
        }

        protected override void OnStart(string[] args)
        {
            log("OnStart");
            lock (lockObject)
            {
                spawnWithoutLock();
            }
            checker = check();
        }

        protected override void OnStop()
        {
            log("OnStop");
            stop();
            checker.Wait();
            ExitCode = 0;
        }

        async Task check()
        {
            while (true)
            {
                lock (lockObject)
                {
                    if (process == null)
                    {
                        return;
                    }

                    if (process.HasExited)
                    {
                        spawnWithoutLock();
                        log("find stopped process so restart");
                    }
                }
                await Task.Delay(checkIntervalMillseconds).ConfigureAwait(false);
            }
        }

        void spawnWithoutLock()
        {
            var info = new ProcessStartInfo(exePath);
            info.CreateNoWindow = true;
            info.UseShellExecute = false;
            info.RedirectStandardError = true;
            info.RedirectStandardInput = true;
            info.RedirectStandardOutput = true;
            info.CreateNoWindow = true;
            info.ErrorDialog = false;
            info.WindowStyle = ProcessWindowStyle.Hidden;

            process = Process.Start(info);
        }

        void stop()
        {
            lock (lockObject)
            {
                if (process != null)
                {
                    if (!process.HasExited)
                    {
                        process.Kill();
                    }
                    process.Close();
                    process = null;
                }
            }
        }

        void log(string format, params object[] args)
        {
            var message = string.Format(format, args);
            EventLog.WriteEntry(message);
        }
    }
}

実行ファイルをWindowsのServiceへ登録

sc.exeコマンドを使うとサービスへの登録、削除、スタートとストップがコマンドラインから実行できます。
「C:\Supervisor」にできたプログラムを設置します。

sc.exe create supervisor binPath= "C:\Supervisor\Suporvisor.exe" start= auto displayname= "Suporvisor"
sc.exe start supervisor

コントロールパネルからサービス一覧を見てみると先ほど登録したものが一覧に追加されます。
services.png

イベントログの確認

コンソールプログラムと違って出力が見れないので、コントロールパネルからイベントビューアーを立ち上げてログを確認します。
うまく動いているようです。
eventlog.png

まとめ

Service登録すると以下のメリットがあります
- Windows Server再起動時に自動起動できる
- Serviceプログラム自体がクラッシュした時に自動再起動したりプログラムを実行したりとリアクションを登録できる
- 簡単にログが残せて標準のイベントビューアーで確認できる

tadokoro
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away