private static void CreateLogfileProcess(IMineContext mineContext, string kernelExeFileFullName, string arguments) { ProcessStartInfo startInfo = new ProcessStartInfo(kernelExeFileFullName, arguments) { UseShellExecute = false, CreateNoWindow = false, WorkingDirectory = MainAssemblyInfo.TempDirFullName }; // 追加环境变量 foreach (var item in mineContext.CoinKernel.EnvironmentVariables) { startInfo.EnvironmentVariables.Add(item.Key, item.Value); } if (_kernelProcess != null) { lock (_kernelProcessLocker) { if (_kernelProcess != null) { _kernelProcess.Dispose(); } } } _kernelProcess = new Process { StartInfo = startInfo }; _kernelProcess.Start(); ReadPrintLoopLogFileAsync(mineContext, isWriteToConsole: false); KernelProcessDaemon(mineContext, null); }
public static void CreateProcess(IMineContext mineContext) { Global.Logger.InfoDebugLine("解压内核包"); // 解压内核包 mineContext.Kernel.ExtractPackage(); string kernelExeFileFullName; string arguments; Global.Logger.InfoDebugLine("组装命令"); // 组装命令 BuildCmdLine(mineContext, out kernelExeFileFullName, out arguments); bool isLogFile = arguments.Contains("{logfile}"); // 这是不应该发生的,如果发生很可能是填写命令的时候拼写错误了 if (!File.Exists(kernelExeFileFullName)) { Global.Logger.ErrorDebugLine(kernelExeFileFullName + "文件不存在,请检查是否有拼写错误"); } if (isLogFile) { Global.Logger.InfoDebugLine("创建日志文件型进程"); // 如果内核支持日志文件 // 推迟打印cmdLine,因为{logfile}变量尚未求值 CreateLogfileProcess(mineContext, kernelExeFileFullName, arguments); } else { Global.Logger.InfoDebugLine("创建管道型进程"); // 如果内核不支持日志文件 string cmdLine = $"\"{kernelExeFileFullName}\" {arguments}"; Global.Logger.InfoDebugLine(cmdLine); CreatePipProcess(mineContext, cmdLine); } }
private static void CreateLogfileProcess(IMineContext mineContext, string kernelExeFileFullName, string arguments) { string logFile = Path.Combine(SpecialPath.LogsDirFullName, "logfile_" + DateTime.Now.Ticks.ToString() + ".log"); arguments = arguments.Replace("{logfile}", logFile); string cmdLine = $"\"{kernelExeFileFullName}\" {arguments}"; Logger.InfoDebugLine(cmdLine); ProcessStartInfo startInfo = new ProcessStartInfo(kernelExeFileFullName, arguments) { UseShellExecute = false, CreateNoWindow = true, WorkingDirectory = VirtualRoot.GlobalDirFullName }; // 追加环境变量 foreach (var item in mineContext.CoinKernel.EnvironmentVariables) { startInfo.EnvironmentVariables.Add(item.Key, item.Value); } Process process = new Process { StartInfo = startInfo }; process.Start(); ReadPrintLoopLogFileAsync(mineContext, logFile); Daemon(mineContext, null); }
public void Pick(Guid kernelId, ref string input, IMineContext mineContext) { try { InitOnece(); if (!_dicById.ContainsKey(kernelId)) { return; } if (string.IsNullOrEmpty(input)) { return; } IKernelOutput kernelOutput = _dicById[kernelId]; ICoin coin = mineContext.MainCoin; bool isDual = false; if ((mineContext is IDualMineContext dualMineContext) && !input.Contains(mineContext.MainCoin.Code)) { isDual = true; coin = dualMineContext.DualCoin; } PickTotalSpeed(_root, input, kernelOutput, coin, isDual); PickGpuSpeed(_root, input, kernelOutput, coin, isDual); PickTotalShare(_root, input, kernelOutput, coin, isDual); PickAcceptShare(_root, input, kernelOutput, coin, isDual); PickAcceptOneShare(_root, input, kernelOutput, coin, isDual); PickRejectPattern(_root, input, kernelOutput, coin, isDual); PickRejectOneShare(_root, input, kernelOutput, coin, isDual); PickRejectPercent(_root, input, kernelOutput, coin, isDual); } catch (Exception e) { Logger.ErrorDebugLine(e.Message, e); } }
private static void ReadPrintLoopLogFile(IMineContext mineContext, string logFile) { bool isLogFileCreated = true; int n = 0; while (!File.Exists(logFile)) { if (n >= 10) { // 10秒钟都没有建立日志文件,不可能 isLogFileCreated = false; break; } Thread.Sleep(1000); if (mineContext != Current.CurrentMineContext) { isLogFileCreated = false; break; } n++; } if (isLogFileCreated) { using (FileStream stream = File.Open(logFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) using (StreamReader sreader = new StreamReader(stream, Encoding.Default)) { while (mineContext == Current.CurrentMineContext) { string outline = sreader.ReadLine(); if (string.IsNullOrEmpty(outline)) { Thread.Sleep(1000); } else { string input = outline; Guid kernelOutputId = mineContext.Kernel.KernelOutputId; Current.KernelOutputFilterSet.Filter(kernelOutputId, ref input); ConsoleColor color = ConsoleColor.White; Current.KernelOutputTranslaterSet.Translate(kernelOutputId, ref input, ref color, isPre: true); // 使用Claymore挖其非ETH币种时它也打印ETH,所以这里需要纠正它 if ("Claymore".Equals(mineContext.Kernel.Code, StringComparison.OrdinalIgnoreCase)) { if (mineContext.MainCoin.Code != "ETH" && input.Contains("ETH")) { input = input.Replace("ETH", mineContext.MainCoin.Code); } } Current.KernelOutputSet.Pick(kernelOutputId, ref input, mineContext); Current.KernelOutputTranslaterSet.Translate(kernelOutputId, ref input, ref color); if (!string.IsNullOrEmpty(input)) { Global.WriteLine(input, color); } } } } Global.Logger.WarnWriteLine("日志输出结束"); } }
public void Pick(Guid kernelOutputId, ref string input, IMineContext mineContext) { try { InitOnece(); if (!_dicById.TryGetValue(kernelOutputId, out KernelOutputData kernelOutput)) { return; } if (string.IsNullOrEmpty(input)) { return; } if (!string.IsNullOrEmpty(kernelOutput.KernelRestartKeyword) && input.Contains(kernelOutput.KernelRestartKeyword)) { mineContext.KernelSelfRestartCount = mineContext.KernelSelfRestartCount + 1; VirtualRoot.Happened(new KernelSelfRestartedEvent()); } ICoin coin = mineContext.MainCoin; bool isDual = false; // 如果是双挖上下文且当前输入行中没有主币关键字则视为双挖币 if ((mineContext is IDualMineContext dualMineContext) && !input.Contains(mineContext.MainCoin.Code)) { isDual = true; coin = dualMineContext.DualCoin; } // 这些方法输出的是事件消息 PickTotalSpeed(_root, input, kernelOutput, coin, isDual); PickGpuSpeed(input, kernelOutput, coin, isDual); PickTotalShare(_root, input, kernelOutput, coin, isDual); PickAcceptShare(_root, input, kernelOutput, coin, isDual); PickAcceptOneShare(_root, input, kernelOutput, coin, isDual); PickRejectPattern(_root, input, kernelOutput, coin, isDual); PickRejectOneShare(_root, input, kernelOutput, coin, isDual); PickRejectPercent(_root, input, kernelOutput, coin, isDual); PickPoolDelay(input, kernelOutput, isDual); // 如果是像BMiner那样的主币和双挖币的输出在同一行那样的模式则一行输出既要视为主币又要视为双挖币 if (isDual && kernelOutput.IsDualInSameLine) { coin = mineContext.MainCoin; isDual = false; PickTotalSpeed(_root, input, kernelOutput, coin, isDual); PickGpuSpeed(input, kernelOutput, coin, isDual); PickTotalShare(_root, input, kernelOutput, coin, isDual); PickAcceptShare(_root, input, kernelOutput, coin, isDual); PickAcceptOneShare(_root, input, kernelOutput, coin, isDual); PickRejectPattern(_root, input, kernelOutput, coin, isDual); PickRejectOneShare(_root, input, kernelOutput, coin, isDual); PickRejectPercent(_root, input, kernelOutput, coin, isDual); PickPoolDelay(input, kernelOutput, isDual); } } catch (Exception e) { Logger.ErrorDebugLine(e); } }
private static void KernelProcessDaemon(IMineContext mineContext, Action clear) { if (_kernelProcessDaemon != null) { VirtualRoot.UnPath(_kernelProcessDaemon); _kernelProcessDaemon = null; clear?.Invoke(); } string processName = mineContext.Kernel.GetProcessName(); _kernelProcessDaemon = VirtualRoot.On <Per1MinuteEvent>("周期性检查挖矿内核是否消失,如果消失尝试重启", LogEnum.DevConsole, action: message => { if (mineContext == Instance.CurrentMineContext) { if (!string.IsNullOrEmpty(processName)) { Process[] processes = Process.GetProcessesByName(processName); if (processes.Length == 0) { mineContext.AutoRestartKernelCount = mineContext.AutoRestartKernelCount + 1; Logger.ErrorWriteLine(processName + $"挖矿内核进程消失"); if (Instance.MinerProfile.IsAutoRestartKernel && mineContext.AutoRestartKernelCount <= Instance.MinerProfile.AutoRestartKernelTimes) { Logger.WarnWriteLine($"尝试第{mineContext.AutoRestartKernelCount}次重启,共{Instance.MinerProfile.AutoRestartKernelTimes}次"); Instance.RestartMine(); Instance.CurrentMineContext.AutoRestartKernelCount = mineContext.AutoRestartKernelCount; } else { Instance.StopMineAsync(); } if (_kernelProcessDaemon != null) { VirtualRoot.UnPath(_kernelProcessDaemon); clear?.Invoke(); } } } } else { if (_kernelProcessDaemon != null) { VirtualRoot.UnPath(_kernelProcessDaemon); _kernelProcessDaemon = null; clear?.Invoke(); } } }); }
private static void KernelProcessDaemon(IMineContext mineContext, Action clear) { if (_kernelProcessDaemon != null) { VirtualRoot.DeletePath(_kernelProcessDaemon); _kernelProcessDaemon = null; clear?.Invoke(); } string processName = mineContext.Kernel.GetProcessName(); _kernelProcessDaemon = VirtualRoot.BuildEventPath <Per1MinuteEvent>("周期性检查挖矿内核是否消失,如果消失尝试重启", LogEnum.DevConsole, action: message => { if (mineContext == Instance.LockedMineContext) { if (!string.IsNullOrEmpty(processName)) { Process[] processes = Process.GetProcessesByName(processName); if (processes.Length == 0) { mineContext.AutoRestartKernelCount += 1; VirtualRoot.ThisLocalWarn(nameof(NTMinerRoot), processName + $"挖矿内核进程消失", toConsole: true); if (Instance.MinerProfile.IsAutoRestartKernel && mineContext.AutoRestartKernelCount <= Instance.MinerProfile.AutoRestartKernelTimes) { VirtualRoot.ThisLocalInfo(nameof(NTMinerRoot), $"尝试第{mineContext.AutoRestartKernelCount.ToString()}次重启,共{Instance.MinerProfile.AutoRestartKernelTimes.ToString()}次", toConsole: true); Instance.RestartMine(); Instance.LockedMineContext.AutoRestartKernelCount = mineContext.AutoRestartKernelCount; } else { Instance.StopMineAsync(StopMineReason.KernelProcessLost); } if (_kernelProcessDaemon != null) { VirtualRoot.DeletePath(_kernelProcessDaemon); clear?.Invoke(); } } } } else { if (_kernelProcessDaemon != null) { VirtualRoot.DeletePath(_kernelProcessDaemon); _kernelProcessDaemon = null; clear?.Invoke(); } } }); }
private static void Daemon(IMineContext mineContext, Action clear) { if (_sDaemon != null) { VirtualRoot.UnPath(_sDaemon); _sDaemon = null; clear?.Invoke(); } string processName = mineContext.Kernel.GetProcessName(); _sDaemon = VirtualRoot.On <Per1MinuteEvent>("周期性检查挖矿内核是否消失,如果消失尝试重启", LogEnum.DevConsole, action: message => { if (mineContext == Current.CurrentMineContext) { if (!string.IsNullOrEmpty(processName)) { Process[] processes = Process.GetProcessesByName(processName); if (processes.Length == 0) { mineContext.ProcessDisappearedCound = mineContext.ProcessDisappearedCound + 1; Logger.ErrorWriteLine(processName + $"挖矿内核进程消失"); if (Current.MinerProfile.IsAutoRestartKernel && mineContext.ProcessDisappearedCound <= 3) { Logger.WarnWriteLine($"尝试第{mineContext.ProcessDisappearedCound}次重启,共3次"); Current.RestartMine(); Current.CurrentMineContext.ProcessDisappearedCound = mineContext.ProcessDisappearedCound; } else { Current.StopMineAsync(); } if (_sDaemon != null) { VirtualRoot.UnPath(_sDaemon); clear?.Invoke(); } } } } else { if (_sDaemon != null) { VirtualRoot.UnPath(_sDaemon); clear?.Invoke(); } } }); }
public static void CreateProcessAsync(IMineContext mineContext) { Task.Factory.StartNew(() => { try { Windows.TaskKill.Kill(mineContext.Kernel.GetProcessName(), waitForExit: true); Thread.Sleep(1000); if (_preExtractPackage != mineContext.Kernel.Package) { _preExtractPackage = mineContext.Kernel.Package; Logger.InfoDebugLine("解压内核包"); // 解压内核包 if (!mineContext.Kernel.ExtractPackage()) { VirtualRoot.Happened(new StartingMineFailedEvent("内核解压失败。")); } } Logger.InfoDebugLine("组装命令"); // 组装命令 BuildCmdLine(mineContext, out var kernelExeFileFullName, out var arguments); bool isLogFile = arguments.Contains("{logfile}"); // 这是不应该发生的,如果发生很可能是填写命令的时候拼写错误了 if (!File.Exists(kernelExeFileFullName)) { Logger.ErrorDebugLine(kernelExeFileFullName + "文件不存在,请检查是否有拼写错误"); } if (isLogFile) { Logger.InfoDebugLine("创建日志文件型进程"); // 如果内核支持日志文件 // 推迟打印cmdLine,因为{logfile}变量尚未求值 CreateLogfileProcess(mineContext, kernelExeFileFullName, arguments); } else { Logger.InfoDebugLine("创建管道型进程"); // 如果内核不支持日志文件 CreatePipProcess(mineContext, kernelExeFileFullName, arguments); } Write.UserOk("开始挖矿"); VirtualRoot.Happened(new MineStartedEvent(mineContext)); } catch (Exception e) { Logger.ErrorDebugLine(e.Message, e); Write.UserFail("挖矿内核启动失败,请联系开发人员解决"); } }); }
public static void CreateProcessAsync(IMineContext mineContext) { Task.Factory.StartNew(() => { lock (_locker) { try { #if DEBUG Write.Stopwatch.Restart(); #endif // 清理除当前外的Temp/Kernel Cleaner.Instance.Clear(); #if DEBUG Write.DevTimeSpan($"耗时{Write.Stopwatch.ElapsedMilliseconds}毫秒 {nameof(MinerProcess)}.{nameof(CreateProcessAsync)}[{nameof(Cleaner)}.{nameof(Cleaner.Clear)}]"); #endif Write.UserOk("场地打扫完毕"); // 应用超频 if (Instance.GpuProfileSet.IsOverClockEnabled(mineContext.MainCoin.GetId())) { Write.UserWarn("应用超频,如果CPU性能较差耗时可能超过1分钟,请耐心等待"); var cmd = new CoinOverClockCommand(mineContext.MainCoin.GetId()); // N卡超频当cpu性能非常差时较耗时,所以这里弄个回调 IMessagePathId callback = null; callback = VirtualRoot.BuildEventPath <CoinOverClockDoneEvent>("超频完成后继续流程", LogEnum.DevConsole, message => { if (mineContext != Instance.CurrentMineContext) { VirtualRoot.DeletePath(callback); } else if (message.CmdId == cmd.Id) { VirtualRoot.DeletePath(callback); ContinueCreateProcess(mineContext); } }); VirtualRoot.Execute(cmd); } else { ContinueCreateProcess(mineContext); } } catch (Exception e) { Logger.ErrorDebugLine(e); Write.UserFail("挖矿内核启动失败,请联系开发人员解决"); } } }); }
private static void Execute(IMineContext mineContext, IFileWriter writer) { try { string content = string.Empty; mineContext.FileWriters.TryGetValue(writer.GetId(), out content); if (!string.IsNullOrEmpty(content)) { // 因为内核日志文件名不是提前确定的而是创建进程前确定的 content = content.Replace(NTKeyword.LogFileParameterName, mineContext.LogFileFullName); string fileFullName = Path.Combine(mineContext.Kernel.GetKernelDirFullName(), writer.FileUrl); File.WriteAllText(fileFullName, content); } } catch (Exception e) { Logger.ErrorDebugLine(e); } }
public static void CreateProcessAsync(IMineContext mineContext) { Task.Factory.StartNew(() => { try { Windows.TaskKill.Kill(mineContext.Kernel.GetProcessName()); Thread.Sleep(1000); Logger.InfoDebugLine("解压内核包"); // 解压内核包 mineContext.Kernel.ExtractPackage(); Logger.InfoDebugLine("组装命令"); // 组装命令 BuildCmdLine(mineContext, out var kernelExeFileFullName, out var arguments); bool isLogFile = arguments.Contains("{logfile}"); // 这是不应该发生的,如果发生很可能是填写命令的时候拼写错误了 if (!File.Exists(kernelExeFileFullName)) { Logger.ErrorDebugLine(kernelExeFileFullName + "文件不存在,请检查是否有拼写错误"); } if (isLogFile) { Logger.InfoDebugLine("创建日志文件型进程"); // 如果内核支持日志文件 // 推迟打印cmdLine,因为{logfile}变量尚未求值 CreateLogfileProcess(mineContext, kernelExeFileFullName, arguments); } else { Logger.InfoDebugLine("创建管道型进程"); // 如果内核不支持日志文件 string cmdLine = $"\"{kernelExeFileFullName}\" {arguments}"; Logger.InfoDebugLine(cmdLine); CreatePipProcess(mineContext, cmdLine); } VirtualRoot.Happened(new MineStartedEvent(mineContext)); } catch (Exception e) { Logger.ErrorDebugLine(e.Message, e); } }); }
private static void CreateLogfileProcess(IMineContext mineContext, string kernelExeFileFullName, string arguments) { string logFile = Path.Combine(SpecialPath.LogsDirFullName, "logfile_" + DateTime.Now.Ticks.ToString() + ".log"); arguments = arguments.Replace("{logfile}", logFile); string cmdLine = $"\"{kernelExeFileFullName}\" {arguments}"; Logger.InfoDebugLine(cmdLine); ProcessStartInfo startInfo = new ProcessStartInfo(kernelExeFileFullName, arguments) { UseShellExecute = false, CreateNoWindow = true, WorkingDirectory = SpecialPath.KernelsDirFullName }; Process process = new Process(); process.StartInfo = startInfo; process.Start(); ReadPrintLoopLogFileAsync(mineContext, logFile); Daemon(mineContext, null); }
private static void PicGpuRejectShare(INTMinerContext context, IMineContext mineContext, string line, IKernelOutput kernelOutput, bool isDual) { string gpuRejectSharePattern = kernelOutput.GpuRejectShare; if (isDual) { return; } if (string.IsNullOrEmpty(gpuRejectSharePattern)) { return; } Regex regex = VirtualRoot.GetRegex(gpuRejectSharePattern); Match match = regex.Match(line); if (match.Success) { string gpuText = match.Groups[NTKeyword.GpuIndexGroupName].Value; string rejectShareText = match.Groups[NTKeyword.RejectShareGroupName].Value; if (!string.IsNullOrEmpty(gpuText)) { if (int.TryParse(gpuText, out int gpuIndex)) { if (IsMapGpuIndex(context, mineContext, kernelOutput) && gpuIndex < mineContext.UseDevices.Length) { gpuIndex = mineContext.UseDevices[gpuIndex]; } if (!string.IsNullOrEmpty(rejectShareText)) { if (int.TryParse(rejectShareText, out int rejectShare)) { context.GpusSpeed.SetRejectShare(gpuIndex, rejectShare); // TODO:如果gpuTotal的拒绝份额为0,求和拒绝份额 } } } } } }