首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

Tamir.SharpSsh SSH命令執行完成判斷:Shell提示符檢測與期望輸出匹配

     編輯:程式設計綜合問答

問題背景

用Ssh.Write()發送命令後,需等待執行完成再Ssh.ReadResponse()讀取完整輸出。Thread.Sleep不可靠(命令耗時不定)。

核心解決思路:檢測Shell提示符

Linux Shell命令執行完畢會輸出提示符(如user@host:~$、root@server:#),以此為標誌判斷完成。

實現代碼

public string ExecuteCommand(string command, string promptRegex = @"[$#>]\s*$", int timeoutMs = 30000) {
    ssh.Write(command + "\n");
    
    StringBuilder output = new StringBuilder();
    DateTime start = DateTime.Now;
    string line;
    
    while ((DateTime.Now - start).TotalMilliseconds < timeoutMs) {
        line = ssh.ReadResponse(); // 非阻塞讀取可用數據
        if (!string.IsNullOrEmpty(line)) {
            output.Append(line);
            // 檢測最後一行是否匹配提示符
            string lastLine = line.Split('\n').LastOrDefault(l => !string.IsNullOrWhiteSpace(l));
            if (Regex.IsMatch(lastLine, promptRegex)) {
                break; // 命令執行完成
            }
        }
        Thread.Sleep(50); // 避免忙等待
    }
    return output.ToString();
}

進階:期望輸出模式匹配

  • 某些命令無固定提示符(如top、tail -f),需約定結束標記:
ssh.Write("echo 'CMD_START'\n");
ssh.Write(command + "\n");
ssh.Write("echo 'CMD_END'\n");
// 讀取直到出現 CMD_END

關鍵點總結

  1. 非阻塞讀取循環:持續ReadResponse()累積輸出,而非單次讀取。
  2. 提示符正則:預設[$#>]\s*$覆蓋bash/zsh/root/common用戶,可配置化。
  3. 超時保護:防止死循環,拋出異常或返回部分結果。
  4. 編碼處理:確保ssh.Encoding匹配服務端Locale(通常UTF-8)。

替代方案

  • 升級SSH.NET(Renci.SshNet),官方維護、支持RunCommand、Expect模式、異步API。
  • 使用expect腳本(Linux原生)包裝複雜交互流程。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved