如何使用C#杀掉Linux系统中指定用户名下的所有进程
C# 实现Linux下杀掉指定用户所有进程的方案
核心问题解决:获取进程所属用户
Linux系统下获取进程所属用户有两种稳定实现方式:
- 方式1:解析
/proc/[pid]/status系统文件
每个运行中进程的元数据都存在/proc/对应pid目录下,status文件中Uid行的第一个值为进程所属用户的uid,再读取/etc/passwd文件匹配uid对应的用户名即可。该方式无需依赖外部命令,纯C#代码即可实现。 - 方式2:调用
ps系统命令直接读取
执行ps -eo pid,user --no-headers命令可以直接输出所有进程的pid和对应用户名,解析输出结果即可拿到映射关系。该方式代码更简单,兼容性更好,不需要处理不同发行版的proc文件格式差异。
完整实现代码
工具方法:解析proc文件获取进程所有者
using System.Diagnostics; using System.Security.Principal; // 根据pid获取进程所属用户名 private static string GetProcessOwner(int pid) { var statusPath = $"/proc/{pid}/status"; if (!File.Exists(statusPath)) return null; foreach (var line in File.ReadAllLines(statusPath)) { if (!line.StartsWith("Uid:")) continue; var parts = line.Split('\t', StringSplitOptions.RemoveEmptyEntries); if (parts.Length < 2 || !uint.TryParse(parts[1], out var uid)) break; // 从/etc/passwd匹配uid对应用户名 foreach (var pwdLine in File.ReadAllLines("/etc/passwd")) { var pwdParts = pwdLine.Split(':'); if (pwdParts.Length >= 3 && pwdParts[2] == uid.ToString()) { return pwdParts[0]; } } break; } return null; }
核心方法:杀掉指定用户所有进程
public static void KillAllProcessesByUser(string targetUserName) { // 获取系统所有运行中的进程 var allProcesses = Process.GetProcesses(); foreach (var process in allProcesses) { try { var owner = GetProcessOwner(process.Id); // 匹配到目标用户的进程则杀掉 if (string.Equals(owner, targetUserName, StringComparison.Ordinal)) { process.Kill(); // 可选:等待进程退出 process.WaitForExit(2000); Console.WriteLine($"已杀死进程{process.Id}({process.ProcessName})"); } } catch (Exception ex) { // 忽略进程已退出、权限不足等异常,也可根据业务需要记录日志 Console.WriteLine($"处理进程{process.Id}失败:{ex.Message}"); } } }
可选简化实现:通过ps命令获取进程所有者
如果你不想自己解析proc文件,可以用这个方法直接获取所有进程和所有者的映射:
private static Dictionary<int, string> GetProcessOwnerMapByPs() { var result = new Dictionary<int, string>(); var startInfo = new ProcessStartInfo("ps", "-eo pid,user --no-headers") { RedirectStandardOutput = true, UseShellExecute = false, CreateNoWindow = true }; using var psProc = Process.Start(startInfo); psProc.WaitForExit(); var output = psProc.StandardOutput.ReadToEnd(); foreach (var line in output.Split('\n', StringSplitOptions.RemoveEmptyEntries)) { var parts = line.Trim().Split(new[] {' '}, StringSplitOptions.RemoveEmptyEntries); if (parts.Length >= 2 && int.TryParse(parts[0], out var pid)) { result[pid] = parts[1]; } } return result; }
注意事项
- 如果你要杀掉其他用户的进程,程序必须以root权限运行,否则会触发权限不足异常
- 如果需要更温和的杀进程逻辑,可以先发送
SIGTERM信号让进程主动退出,等待几秒未退出再调用Kill()方法发送SIGKILL强杀 - 遍历进程过程中部分临时进程可能已经退出,代码中已经加了异常捕获逻辑,不需要额外处理
内容的提问来源于stack exchange,提问作者Ritik Agarwal
相关产品推荐
相关产品推荐

