C#调用CMD通过SSH访问本地部署Git服务器执行命令获取日志问题
问题根因
你之前的写法存在两个核心逻辑错误:
- SSH命令执行逻辑错误:
ssh swx@192.168.12.232 && cd git_home && git log的语义是本地先执行SSH连接命令,等SSH进程完全退出且返回成功后,再在本地执行后续的cd、git log命令,自然不会在远程服务器运行 - 交互式写入命令逻辑错误:直接向本地CMD的标准输入写入命令时,SSH连接建立后没有等待会话初始化完成,后续的命令直接被本地CMD进程接收执行,没有传递到远程服务器
最简修复方案:SSH直接携带远程命令执行
SSH本身支持在连接参数后直接拼接需要远程执行的命令,多个命令用引号包裹即可,不需要额外操作标准输入流,代码如下:
using System.Diagnostics; using System.Text; ProcessStartInfo startInfo = new ProcessStartInfo { FileName = "ssh.exe", // 核心:把需要远程执行的命令用引号包裹,直接跟在SSH连接参数后 Arguments = "swx@192.168.12.232 \"cd git_home && git log\"", WorkingDirectory = @"C:\Users\xyz\.ssh", WindowStyle = ProcessWindowStyle.Hidden, RedirectStandardOutput = true, RedirectStandardError = true, UseShellExecute = false, // 可根据远程服务器的编码调整,避免中文乱码 StandardOutputEncoding = Encoding.UTF8, StandardErrorEncoding = Encoding.UTF8 }; using Process process = Process.Start(startInfo); process.WaitForExit(); // 读取执行结果 string returnValue = process.StandardOutput.ReadToEnd(); // 可读取错误输出排查问题 string errorMsg = process.StandardError.ReadToEnd();
这个方案不需要套一层cmd.exe,直接调用系统自带的ssh.exe,逻辑更简洁,稳定性更高。
生产级优化方案:使用SSH.NET库
如果后续有大量远程操作需求,建议直接使用SSH.NET库,不需要依赖本地SSH客户端,可操作性和稳定性更强:
- 首先通过NuGet安装
SSH.NET包 - 代码示例:
using Renci.SshNet; // 读取本地私钥,支持免密登录 var privateKey = new PrivateKeyFile(@"C:\Users\xyz\.ssh\id_rsa"); using var sshClient = new SshClient("192.168.12.232", "swx", privateKey); sshClient.Connect(); // 执行远程命令 var commandResult = sshClient.RunCommand("cd git_home && git log"); // 直接获取输出结果 string returnValue = commandResult.Result; // 错误输出 string errorMsg = commandResult.Error; sshClient.Disconnect();
可选方案:交互式SSH会话(不推荐生产环境使用)
如果确实需要用交互式会话执行多命令,需要等待SSH连接建立完成后再写入远程命令,示例如下:
using System.Diagnostics; using System.Text; using System.Threading; ProcessStartInfo info = new ProcessStartInfo { FileName = "cmd.exe", RedirectStandardInput = true, RedirectStandardOutput = true, UseShellExecute = false, StandardOutputEncoding = Encoding.UTF8 }; using Process p = Process.Start(info); using var sw = p.StandardInput; if (sw.BaseStream.CanWrite) { sw.WriteLine(@"cd C:\Users\xyz\.ssh"); sw.WriteLine("ssh swx@192.168.12.232"); // 等待SSH连接建立完成,时长可根据网络情况调整 Thread.Sleep(2000); // 写入远程命令 sw.WriteLine("cd git_home && git log"); // 退出远程SSH会话 sw.WriteLine("exit"); // 退出本地CMD sw.WriteLine("exit"); } p.WaitForExit(); string returnValue = p.StandardOutput.ReadToEnd();
该方案依赖固定时长等待连接,容易受网络波动影响导致执行失败,仅适合测试场景使用。
内容的提问来源于stack exchange,提问作者swx
相关产品推荐
相关产品推荐

