public static (int, string) GitCloneRepo(List <string> hosts, string repoUrl, string user, string password, int sshPort, string commit = "", string branch = "origin/master", string repoRoot = "/home/wanl/signalr_auto_test_framework") { var errCode = 0; var result = ""; var tasks = new List <Task>(); hosts.ForEach(host => { if (host.Contains("localhost") || host.Contains("127.0.0.1")) { return; } tasks.Add(Task.Run(() => { var errCodeInner = 0; var resultInner = ""; var remoteScriptContent = $@" #!/bin/bash if [ -d {repoRoot} ] then rm -rf {repoRoot} fi git clone {repoUrl} {repoRoot} rtn=$? ## re-check whether repo was cloned successfully v=0 while [ $rtn -ne 0 ] && [ $v -lt 3 ] do if [ -d {repoRoot} ] then rm -rf {repoRoot} fi git clone {repoUrl} {repoRoot} rtn=$? if [ $rtn -eq 0 ] then break fi v=$(($v+1)) done cd {repoRoot} git checkout {branch} "; var scriptFile = "remoteScript.sh"; using (StreamWriter sw = new StreamWriter(scriptFile)) { sw.Write(remoteScriptContent); } var innerCmd = $"chmod +x {scriptFile}; ./{scriptFile}"; var i = 0; var retry = 3; while (i < retry) { (errCode, result) = ShellHelper.ScpFileLocalToRemote(user, host, password, scriptFile, "~/"); if (errCode != 0) { Console.WriteLine("Fail to copy script from local to remote: {errCode}"); } (errCodeInner, resultInner) = ShellHelper.RemoteBash(user, host, sshPort, password, innerCmd); if (errCodeInner != 0) { errCode = errCodeInner; result = resultInner; } else { break; } i++; } })); }); Task.WhenAll(tasks).Wait(); if (errCode != 0) { Util.Log($"ERR {errCode}: {result}"); Environment.Exit(1); } return(errCode, result); }