C#スクリプトは端末で待機しますが、デーモンプロセスで直接終了します。

C#スクリプトは端末で待機しますが、デーモンプロセスで直接終了します。
  • 私は完全なC#初心者です(Javaを知っていますが)。
  • C#スクリプトを修正しました。起動時にデーモンとsystemctlを使用して実行したかったです(元々NZXT自動ファンコントローラスクリプト)
  • このコードは、4秒ごとにコードスニペットを実行し、次を使用して終了スクリプトをブロックする反復タイマーを生成します。Console.ReadLine();
  • mscとmonoを使用してスクリプトをコンパイルしてテストしました。端末で期待どおりに動作します(直接終了しません)。
  • デーモンとして実行するとConsole.ReadLine();待ち時間がなく、スクリプトは基本メソッドを直接完了して終了します。
  • メモ:

    • 私もLinux moobなので、デーモンで何か間違っている場合は指摘してください。私の目標は、起動時にシステムを起動および停止できるバックグラウンドスクリプトを作成することです。
    • 以下に添付されているすべてのコードを見つけてください。

主なコード:

using System;
using System.IO;
using System.Timers;
using System.Threading.Tasks;
using System.Diagnostics;
using System.Text.RegularExpressions;

public class Program
{

    private static string root;
    private static string confFile = "/home/mohammadah/scripts/grid+v2/conf.d";
    private static System.Timers.Timer aTimer;

    private static int maxSpeed = 100;
    private static int minSpeed = 35;
    // do not change this. all fan speeds have to rounded to the nearest multiple of 5
    private static int minimumRound = 5;
    private static int timerTime = 4000;
    private static int defaultFanSpeed = 40;

    // fans: 
    // 1: empty
    // 2: empty
    // 3: bottom
    // 4: top
    // 5: CPU
    // 6: Back
    private static int[] gpuFans;
    private static int gpuMaxTemp;
    private static int gpuMinTemp;

    private static int[] cpuFans;
    private static int cpuMaxTemp;
    private static int cpuMinTemp;

    private static float lastCPUSpeed = 0;
    private static float lastGPUSpeed = 0;

    public static void Main()
    {
    //    Console.WriteLine(System.IO.Path.GetDirectoryName(Application.ExecutablePath));
       ParseConfigFile(confFile);


        if(!Regex.IsMatch(DoGridCommand("get fan 1"), @"Fan 1: \d{1,5} RPM")){
            DoGridCommand("init");
        }

        DoGridCommand("set fans all speed " + defaultFanSpeed);

        

        SetTimer();
        Console.WriteLine("\nPress the Enter key to exit the application...\n");
        // Process.GetCurrentProcess().WaitForExit();

        Console.ReadLine();
        aTimer.Stop();
        aTimer.Dispose();
        Console.WriteLine("Terminating the application...");
    }

    private static float GetGPUTemp(){
        ProcessStartInfo procStartInfo = new ProcessStartInfo("/bin/bash", "-c nvidia-smi -q -d temperature");
        procStartInfo.RedirectStandardOutput = true;
        procStartInfo.UseShellExecute = false;
        procStartInfo.CreateNoWindow = true;

        System.Diagnostics.Process proc = new System.Diagnostics.Process();
        proc.StartInfo = procStartInfo;
        proc.Start();
        string result = proc.StandardOutput.ReadToEnd();
        
        char first = '-';
        char second = '-';
        string temp = "";

        foreach (char c in result)
        {
            if(c=='1' || c == '2'|| c == '3'|| c == '4'|| c == '5'|| c == '6'|| c == '7'|| c == '8'|| c == '9'|| c == '0'|| c == 'C'){
                if(first == '-'){
                    first = c;
                }else if(second == '-'){
                    second = c;
                }else if(c == 'C'){
                    temp = "" + first + second;
                    break;
                }
            }else{
                first = '-';
                second = '-';
            }
        }
        return float.Parse(temp);
    }

    private static int GetCPUTemp(){

        string tempLineStart = "Packageid0:+";

        ProcessStartInfo procStartInfo = new ProcessStartInfo("/bin/bash", "-c sensors");
        procStartInfo.RedirectStandardOutput = true;
        procStartInfo.UseShellExecute = false;
        procStartInfo.CreateNoWindow = true;

        System.Diagnostics.Process proc = new System.Diagnostics.Process();
        proc.StartInfo = procStartInfo;
        proc.Start();

        int temp = 0;
        string line = "";
        while ((line = proc.StandardOutput.ReadLine()) != null) {
            line = Regex.Replace(line, @"\s+", "");
            if(Regex.IsMatch(line, tempLineStart)){
                line = line.Trim().Replace(tempLineStart.Trim(), "");
                line = line.Substring(0, 6);
                line = Regex.Replace(line, "[^0-9.]", "");
                float t = float.Parse(line);
                temp = (int)t;
                break;
            }
        }

        return temp;
    }

    private static void SetTimer()
    {
        // Create a timer with a two second interval.
        aTimer = new System.Timers.Timer(timerTime);
        // Hook up the Elapsed event for the timer. 
        aTimer.Elapsed += OnTimedEvent;
        aTimer.AutoReset = true;
        aTimer.Enabled = true;
    }    

    private static void ParseConfigFile(string fileName){
        string gridfanLocation = "GridfanLocation:";
        string gpuFanLineStart = "GPUFans:";
        string gpuMaxLineStart = "GPUMaxTemp:";
        string gpuMinLineStart = "GPUMinTemp:";
        string cpuFanLineStart = "CPUFans:";
        string cpuMinLineStart = "CPUMinTemp:";
        string cpuMaxLineStart = "CPUMaxTemp:";
    
        StreamReader reader = File.OpenText(fileName);
        string line;    
        while ((line = reader.ReadLine()) != null) {

            line = line.Trim();
            // Regex.Replace(line, @"\s+", "");
            // ignore commented out (starts with "//") or empty lines
            if(line.StartsWith("//") || line.Equals("")) continue;
            // set gpu temp at which gpu fans will be set at 100% speed
            else if(Regex.IsMatch(line, gridfanLocation)){
                root = line.Trim().Replace(gridfanLocation, "");
            // set gpu fan list using the numbering found on gridfan git repo
            }else if(Regex.IsMatch(line, gpuFanLineStart)){
                line = line.Trim().Replace(gpuFanLineStart, "");
                string[] fans = line.Split(",");
                gpuFans = new int[fans.Length];
                for (int i =0;i<fans.Length;i++){
                    gpuFans[i] = int.Parse(fans[i].Trim());
                }
            // set gpu temp at which gpu fans will be set at 100% speed
            } else if(Regex.IsMatch(line, gpuMaxLineStart)){
                line = line.Trim().Replace(gpuMaxLineStart, "");
                gpuMaxTemp = int.Parse(line);
            // set gpu temp at which gpu fans will be set at lowest speed
            } else if(Regex.IsMatch(line, gpuMinLineStart)){
                line = line.Trim().Replace(gpuMinLineStart, "");
                gpuMinTemp = int.Parse(line);
            // set cpu fan list using the numbering found on gridfan git repo
            } else if(Regex.IsMatch(line, cpuFanLineStart)){
                line = line.Trim().Replace(cpuFanLineStart, "");
                string[] fans = line.Split(",");
                cpuFans = new int[fans.Length];
                for (int i =0;i<fans.Length;i++){
                    cpuFans[i] = int.Parse(fans[i].Trim());
                }
            // set cpu temp at which gpu fans will be set at 100% speed
            } else if(Regex.IsMatch(line, cpuMaxLineStart)){
                line = line.Trim().Replace(cpuMaxLineStart, "");
                cpuMaxTemp = int.Parse(line);
            // set cpu temp at which gpu fans will be set at lowest speed
            } else if(Regex.IsMatch(line, cpuMinLineStart)){
                line = line.Trim().Replace(cpuMinLineStart, "");
                cpuMinTemp = int.Parse(line);
            }
            else throw new Exception ("Something went wrong while parsing config file \"./conf.d\"");
        }
    }

    private static void OnTimedEvent(Object source, ElapsedEventArgs e)
    {
        Console.WriteLine("====================================================");
        float gpuTemp = GetGPUTemp();
        Console.WriteLine("Graphics (GPU) temp: " + gpuTemp+"`C");
        float gpuPercentage = 100 * ((gpuTemp - gpuMinTemp) / (gpuMaxTemp - gpuMinTemp));
        Console.WriteLine("Graphics (GPU) percentage: " + gpuPercentage+"`%");
        float gpuFanSpeed = gpuPercentage > maxSpeed ? maxSpeed : gpuPercentage < minSpeed ? minSpeed : gpuPercentage;
        gpuFanSpeed = (int) Math.Ceiling(gpuFanSpeed / minimumRound) * minimumRound;

        if(lastGPUSpeed != gpuFanSpeed){
            if(!Regex.IsMatch(DoGridCommand("get fan 1"), @"Fan 1: \d{1,5} RPM")){
                DoGridCommand("init");
            }
            foreach (int gpuFan in gpuFans){
                DoGridCommand("set fans " + gpuFan + " speed " + gpuFanSpeed);
            }
        }
        float cpuTemp = GetCPUTemp();
        Console.WriteLine("Central (CPU) temp: " + cpuTemp+"`C");
        float cpuPercentage = 100 * ((cpuTemp - cpuMinTemp) / (cpuMaxTemp - cpuMinTemp));
        Console.WriteLine("Central (CPU) percentage: " + cpuPercentage+"`%");
        Console.WriteLine("");
        float cpuFanSpeed = (cpuPercentage > maxSpeed ? maxSpeed : cpuPercentage < minSpeed ? minSpeed : cpuPercentage);
        cpuFanSpeed = (int) Math.Ceiling(cpuFanSpeed / minimumRound) * minimumRound;

        if(lastCPUSpeed != gpuFanSpeed){
            if(!Regex.IsMatch(DoGridCommand("get fan 1"), @"Fan 1: \d{1,5} RPM")){
                DoGridCommand("init");
            }

            foreach (int cpuFan in cpuFans){
                DoGridCommand("set fans " + cpuFan + " speed " + cpuFanSpeed);
            }
        }
        lastCPUSpeed = cpuFanSpeed;
        lastGPUSpeed = gpuFanSpeed;
        Console.WriteLine("====================================================");
        Console.WriteLine();
    }

    private static string DoGridCommand(string command){
        ProcessStartInfo procStartInfo = new ProcessStartInfo("/bin/bash", root + "/gridfan " + command);
        procStartInfo.RedirectStandardOutput = true;
        procStartInfo.UseShellExecute = false;
        procStartInfo.CreateNoWindow = true;

        System.Diagnostics.Process proc = new System.Diagnostics.Process();
        proc.StartInfo = procStartInfo;
        proc.Start();
        string result = proc.StandardOutput.ReadToEnd();
        Console.WriteLine("Command result: " + result.Trim());
        // System.Threading.Thread.Sleep(500);
        return result;
    }
}

メインコードで使用されるconf.d(非常に重要ではありませんが、完成度のために):

// gridFan repo = https://github.com/CapitalF/gridfan
// root of gridFan script location
GridfanLocation:/home/mohammadah/scripts/grid+v2
// GPU fans id/ports as per the schema in gridFan repo readme
GPUFans: 3
// GPU temp at which GPU fans will be set at 100% speed
GPUMaxTemp: 75
// GPU temp at which GPU fans will be set at lowest speed
GPUMinTemp: 35
// GPU fans id/port as per the schema in gridFan repo readme
CPUFans: 4, 5, 6
// CPU temp at which CPU fans will be set at 100% speed
CPUMaxTemp: 75
// CPU temp at which CPU fans will be set at lowest speed
CPUMinTemp: 35

daemon.service ファイル

[Unit]
Description=Grid+ v2 automatic fan controller

[Service]
ExecStart=/usr/bin/mono /home/mohammadah/scripts/grid+v2/LinuxGrid-v2Controller.exe
Restart=on-failure

[Install]
WantedBy=multi-user.target

答え1

わかりませんが、c#問題はsystemdサービスで起動したときにプログラムのSTDINがに接続されているため、読み取りを試みると/dev/nullすぐConsole.ReadLine();に結果(ゼロバイトの読み取り)を取得して返すためと考えられます。

次の方法で同じものを手動で再現できます。

myprog < /dev/null

プログラムが終了しないようにするには、これを実行する別のメカニズムが必要です。

関連情報