mirror of https://github.com/2dust/v2rayN
Optimized and improved the code
Optimized and improved the code for killing core processes in non-Windows environments. Now uses a shell script for precise processing.pull/7673/head
parent
6715d7dce6
commit
3d23f3e3a2
|
@ -223,4 +223,28 @@ public static class FileManager
|
||||||
// ignored
|
// ignored
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Creates a Linux shell file with the specified contents.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="fileName"></param>
|
||||||
|
/// <param name="contents"></param>
|
||||||
|
/// <param name="overwrite"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static async Task<string> CreateLinuxShellFile(string fileName, string contents, bool overwrite)
|
||||||
|
{
|
||||||
|
var shFilePath = Utils.GetBinConfigPath(fileName);
|
||||||
|
|
||||||
|
// Check if the file already exists and if we should overwrite it
|
||||||
|
if (!overwrite && File.Exists(shFilePath))
|
||||||
|
{
|
||||||
|
return shFilePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
File.Delete(shFilePath);
|
||||||
|
await File.WriteAllTextAsync(shFilePath, contents);
|
||||||
|
await Utils.SetLinuxChmod(shFilePath);
|
||||||
|
|
||||||
|
return shFilePath;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,6 +38,8 @@ public class Global
|
||||||
public const string PacFileName = NamespaceSample + "pac";
|
public const string PacFileName = NamespaceSample + "pac";
|
||||||
public const string ProxySetOSXShellFileName = NamespaceSample + "proxy_set_osx_sh";
|
public const string ProxySetOSXShellFileName = NamespaceSample + "proxy_set_osx_sh";
|
||||||
public const string ProxySetLinuxShellFileName = NamespaceSample + "proxy_set_linux_sh";
|
public const string ProxySetLinuxShellFileName = NamespaceSample + "proxy_set_linux_sh";
|
||||||
|
public const string KillAsSudoOSXShellFileName = NamespaceSample + "kill_as_sudo_osx_sh";
|
||||||
|
public const string KillAsSudoLinuxShellFileName = NamespaceSample + "kill_as_sudo_linux_sh";
|
||||||
|
|
||||||
public const string DefaultSecurity = "auto";
|
public const string DefaultSecurity = "auto";
|
||||||
public const string DefaultNetwork = "tcp";
|
public const string DefaultNetwork = "tcp";
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using CliWrap;
|
using CliWrap;
|
||||||
|
using CliWrap.Buffered;
|
||||||
|
|
||||||
namespace ServiceLib.Handler;
|
namespace ServiceLib.Handler;
|
||||||
|
|
||||||
|
@ -11,6 +12,7 @@ public class CoreAdminHandler
|
||||||
private Config _config;
|
private Config _config;
|
||||||
private Action<bool, string>? _updateFunc;
|
private Action<bool, string>? _updateFunc;
|
||||||
private int _linuxSudoPid = -1;
|
private int _linuxSudoPid = -1;
|
||||||
|
private const string _tag = "CoreAdminHandler";
|
||||||
|
|
||||||
public async Task Init(Config config, Action<bool, string> updateFunc)
|
public async Task Init(Config config, Action<bool, string> updateFunc)
|
||||||
{
|
{
|
||||||
|
@ -31,8 +33,11 @@ public class CoreAdminHandler
|
||||||
|
|
||||||
public async Task<Process?> RunProcessAsLinuxSudo(string fileName, CoreInfo coreInfo, string configPath)
|
public async Task<Process?> RunProcessAsLinuxSudo(string fileName, CoreInfo coreInfo, string configPath)
|
||||||
{
|
{
|
||||||
|
StringBuilder sb = new();
|
||||||
|
sb.AppendLine("#!/bin/bash");
|
||||||
var cmdLine = $"{fileName.AppendQuotes()} {string.Format(coreInfo.Arguments, Utils.GetBinConfigPath(configPath).AppendQuotes())}";
|
var cmdLine = $"{fileName.AppendQuotes()} {string.Format(coreInfo.Arguments, Utils.GetBinConfigPath(configPath).AppendQuotes())}";
|
||||||
var shFilePath = await CreateLinuxShellFile(cmdLine, "run_as_sudo.sh");
|
sb.AppendLine($"sudo -S {cmdLine}");
|
||||||
|
var shFilePath = await FileManager.CreateLinuxShellFile("run_as_sudo.sh", sb.ToString(), true);
|
||||||
|
|
||||||
Process proc = new()
|
Process proc = new()
|
||||||
{
|
{
|
||||||
|
@ -87,35 +92,24 @@ public class CoreAdminHandler
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var cmdLine = $"pkill -P {_linuxSudoPid} ; kill {_linuxSudoPid}";
|
try
|
||||||
var shFilePath = await CreateLinuxShellFile(cmdLine, "kill_as_sudo.sh");
|
{
|
||||||
|
var shellFileName = Utils.IsOSX() ? Global.KillAsSudoOSXShellFileName : Global.KillAsSudoLinuxShellFileName;
|
||||||
|
var shFilePath = await FileManager.CreateLinuxShellFile("kill_as_sudo.sh", EmbedUtils.GetEmbedText(shellFileName), true);
|
||||||
|
|
||||||
await Cli.Wrap(shFilePath)
|
var arg = new List<string>() { "-c", $"sudo -S {shFilePath} {_linuxSudoPid}" };
|
||||||
.WithStandardInputPipe(PipeSource.FromString(AppHandler.Instance.LinuxSudoPwd))
|
var result = await Cli.Wrap(Global.LinuxBash)
|
||||||
.ExecuteAsync();
|
.WithArguments(arg)
|
||||||
|
.WithStandardInputPipe(PipeSource.FromString(AppHandler.Instance.LinuxSudoPwd))
|
||||||
|
.ExecuteBufferedAsync();
|
||||||
|
|
||||||
|
UpdateFunc(false, result.StandardOutput.ToString());
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Logging.SaveLog(_tag, ex);
|
||||||
|
}
|
||||||
|
|
||||||
_linuxSudoPid = -1;
|
_linuxSudoPid = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<string> CreateLinuxShellFile(string cmdLine, string fileName)
|
|
||||||
{
|
|
||||||
var shFilePath = Utils.GetBinConfigPath(fileName);
|
|
||||||
File.Delete(shFilePath);
|
|
||||||
|
|
||||||
var sb = new StringBuilder();
|
|
||||||
sb.AppendLine("#!/bin/sh");
|
|
||||||
if (Utils.IsAdministrator())
|
|
||||||
{
|
|
||||||
sb.AppendLine($"{cmdLine}");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
sb.AppendLine($"sudo -S {cmdLine}");
|
|
||||||
}
|
|
||||||
|
|
||||||
await File.WriteAllTextAsync(shFilePath, sb.ToString());
|
|
||||||
await Utils.SetLinuxChmod(shFilePath);
|
|
||||||
|
|
||||||
return shFilePath;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,14 +18,7 @@ public class ProxySettingLinux
|
||||||
|
|
||||||
private static async Task ExecCmd(List<string> args)
|
private static async Task ExecCmd(List<string> args)
|
||||||
{
|
{
|
||||||
var fileName = Utils.GetBinConfigPath(_proxySetFileName);
|
var fileName = await FileManager.CreateLinuxShellFile(_proxySetFileName, EmbedUtils.GetEmbedText(Global.ProxySetLinuxShellFileName), false);
|
||||||
if (!File.Exists(fileName))
|
|
||||||
{
|
|
||||||
var contents = EmbedUtils.GetEmbedText(Global.ProxySetLinuxShellFileName);
|
|
||||||
await File.AppendAllTextAsync(fileName, contents);
|
|
||||||
|
|
||||||
await Utils.SetLinuxChmod(fileName);
|
|
||||||
}
|
|
||||||
|
|
||||||
await Utils.GetCliWrapOutput(fileName, args);
|
await Utils.GetCliWrapOutput(fileName, args);
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,14 +23,7 @@ public class ProxySettingOSX
|
||||||
|
|
||||||
private static async Task ExecCmd(List<string> args)
|
private static async Task ExecCmd(List<string> args)
|
||||||
{
|
{
|
||||||
var fileName = Utils.GetBinConfigPath(_proxySetFileName);
|
var fileName = await FileManager.CreateLinuxShellFile(_proxySetFileName, EmbedUtils.GetEmbedText(Global.ProxySetOSXShellFileName), false);
|
||||||
if (!File.Exists(fileName))
|
|
||||||
{
|
|
||||||
var contents = EmbedUtils.GetEmbedText(Global.ProxySetOSXShellFileName);
|
|
||||||
await File.AppendAllTextAsync(fileName, contents);
|
|
||||||
|
|
||||||
await Utils.SetLinuxChmod(fileName);
|
|
||||||
}
|
|
||||||
|
|
||||||
await Utils.GetCliWrapOutput(fileName, args);
|
await Utils.GetCliWrapOutput(fileName, args);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,61 @@
|
||||||
|
#!/bin/bash
|
||||||
|
#
|
||||||
|
# Process Terminator Script for Linux
|
||||||
|
# This script forcibly terminates a process and all its child processes
|
||||||
|
#
|
||||||
|
|
||||||
|
# Check if PID argument is provided
|
||||||
|
if [ $# -ne 1 ]; then
|
||||||
|
echo "Usage: $0 <PID>"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
PID=$1
|
||||||
|
|
||||||
|
# Validate that input is a valid PID (numeric)
|
||||||
|
if ! [[ "$PID" =~ ^[0-9]+$ ]]; then
|
||||||
|
echo "Error: The PID must be a numeric value"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if the process exists
|
||||||
|
if ! ps -p $PID > /dev/null; then
|
||||||
|
echo "Warning: No process found with PID $PID"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Recursive function to find and kill all child processes
|
||||||
|
kill_children() {
|
||||||
|
local parent=$1
|
||||||
|
local children=$(ps -o pid --no-headers --ppid "$parent")
|
||||||
|
|
||||||
|
# Output information about processes being terminated
|
||||||
|
echo "Processing children of PID: $parent..."
|
||||||
|
|
||||||
|
# Process each child
|
||||||
|
for child in $children; do
|
||||||
|
# Recursively find and kill child's children first
|
||||||
|
kill_children "$child"
|
||||||
|
|
||||||
|
# Force kill the child process
|
||||||
|
echo "Terminating child process: $child"
|
||||||
|
kill -9 "$child" 2>/dev/null || true
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "============================================"
|
||||||
|
echo "Starting termination of process $PID and all its children"
|
||||||
|
echo "============================================"
|
||||||
|
|
||||||
|
# Find and kill all child processes
|
||||||
|
kill_children "$PID"
|
||||||
|
|
||||||
|
# Finally kill the main process
|
||||||
|
echo "Terminating main process: $PID"
|
||||||
|
kill -9 "$PID" 2>/dev/null || true
|
||||||
|
|
||||||
|
echo "============================================"
|
||||||
|
echo "Process $PID and all its children have been terminated"
|
||||||
|
echo "============================================"
|
||||||
|
|
||||||
|
exit 0
|
|
@ -0,0 +1,56 @@
|
||||||
|
#!/bin/bash
|
||||||
|
#
|
||||||
|
# Process Terminator Script for macOS
|
||||||
|
# This script forcibly terminates a process and all its descendant processes
|
||||||
|
#
|
||||||
|
|
||||||
|
# Check if PID argument is provided
|
||||||
|
if [ $# -ne 1 ]; then
|
||||||
|
echo "Usage: $0 <PID>"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
PID=$1
|
||||||
|
|
||||||
|
# Validate that input is a valid PID (numeric)
|
||||||
|
if ! [[ "$PID" =~ ^[0-9]+$ ]]; then
|
||||||
|
echo "Error: The PID must be a numeric value"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if the process exists
|
||||||
|
if ! ps -p $PID > /dev/null; then
|
||||||
|
echo "Warning: No process found with PID $PID"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Recursive function to find and kill all descendant processes
|
||||||
|
kill_descendants() {
|
||||||
|
local parent=$1
|
||||||
|
# Use ps -eo pid,ppid for macOS compatibility
|
||||||
|
local children=$(ps -eo pid=,ppid= | awk -v ppid=$parent '$2==ppid {print $1}')
|
||||||
|
|
||||||
|
echo "Processing children of PID: $parent..."
|
||||||
|
for child in $children; do
|
||||||
|
kill_descendants "$child"
|
||||||
|
echo "Terminating child process: $child"
|
||||||
|
kill -9 "$child" 2>/dev/null || true
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "============================================"
|
||||||
|
echo "Starting termination of process $PID and all its descendants"
|
||||||
|
echo "============================================"
|
||||||
|
|
||||||
|
# Find and kill all descendant processes
|
||||||
|
kill_descendants "$PID"
|
||||||
|
|
||||||
|
# Finally kill the main process
|
||||||
|
echo "Terminating main process: $PID"
|
||||||
|
kill -9 "$PID" 2>/dev/null || true
|
||||||
|
|
||||||
|
echo "============================================"
|
||||||
|
echo "Process $PID and all its descendants have been terminated"
|
||||||
|
echo "============================================"
|
||||||
|
|
||||||
|
exit 0
|
|
@ -28,6 +28,8 @@
|
||||||
<EmbeddedResource Include="Sample\custom_routing_white" />
|
<EmbeddedResource Include="Sample\custom_routing_white" />
|
||||||
<EmbeddedResource Include="Sample\dns_singbox_normal" />
|
<EmbeddedResource Include="Sample\dns_singbox_normal" />
|
||||||
<EmbeddedResource Include="Sample\dns_v2ray_normal" />
|
<EmbeddedResource Include="Sample\dns_v2ray_normal" />
|
||||||
|
<EmbeddedResource Include="Sample\kill_as_sudo_linux_sh" />
|
||||||
|
<EmbeddedResource Include="Sample\kill_as_sudo_osx_sh" />
|
||||||
<EmbeddedResource Include="Sample\pac" />
|
<EmbeddedResource Include="Sample\pac" />
|
||||||
<EmbeddedResource Include="Sample\proxy_set_linux_sh" />
|
<EmbeddedResource Include="Sample\proxy_set_linux_sh" />
|
||||||
<EmbeddedResource Include="Sample\proxy_set_osx_sh" />
|
<EmbeddedResource Include="Sample\proxy_set_osx_sh" />
|
||||||
|
|
|
@ -66,8 +66,7 @@ public partial class SudoPasswordInputView : UserControl
|
||||||
{
|
{
|
||||||
// Use sudo echo command to verify password
|
// Use sudo echo command to verify password
|
||||||
var arg = new List<string>() { "-c", "sudo -S echo SUDO_CHECK" };
|
var arg = new List<string>() { "-c", "sudo -S echo SUDO_CHECK" };
|
||||||
var result = await CliWrap.Cli
|
var result = await CliWrap.Cli.Wrap(Global.LinuxBash)
|
||||||
.Wrap(Global.LinuxBash)
|
|
||||||
.WithArguments(arg)
|
.WithArguments(arg)
|
||||||
.WithStandardInputPipe(CliWrap.PipeSource.FromString(password))
|
.WithStandardInputPipe(CliWrap.PipeSource.FromString(password))
|
||||||
.ExecuteBufferedAsync();
|
.ExecuteBufferedAsync();
|
||||||
|
|
Loading…
Reference in New Issue