SshClient client;
var sethost = client.RunCommand("export DOCKER_HOST=:2375");
var infohost = client.RunCommand("docker info");
var ps = client.RunCommand("docker ps");
我正在使用ssh客户端的上述命令来处理.Net但是它没有保留第一个在下两个命令中执行导出的命令的状态。
如果我手动ssh并按照我的预期执行3个命令,但是上面的c#代码似乎忘记了后续命令中的导出。
答案 0 :(得分:0)
我假设您使用的是SSH.NET库。在下面的解决方案中,我使用了stable version (2013.4.7),它也可以作为NuGet包使用。
有两种可能的解决方案可以让它发挥作用。第一个是将要运行的命令组合在一个RunCommand中。 RunCommand每次调用它时都会启动一个新shell,并且它会忘记您执行的任何环境设置。通过使用&& or ||
运算符链接命令,您可以在同一个Shell中执行所有命令。
static void SolutionOne(ConnectionInfo connection)
{
using (SshClient client = new SshClient(connection))
{
client.ErrorOccurred += (e, s) =>
{
Debug.WriteLine(s.Exception);
};
client.Connect();
// each RunCommand starts its own/new Shell...
var sethost = client.RunCommand("export DOCKER_HOST=:2375");
// ... nothing is kept...
var infohost = client.RunCommand("export -p");
if (!infohost.Result.Contains("DOCKER_HOST"))
{
Console.WriteLine("sorry, a new shell was started for this command");
}
// ... across run commands
var ps = client.RunCommand("echo has value: $DOCKER");
Console.WriteLine(ps.Result);
Console.WriteLine("");
Console.WriteLine("Chain the linux commands...");
// chain all commands with &&
var concatAll = client.RunCommand("export DOCKER_HOST=:2375 && export -p | grep DO && echo has value: $DOCKER_HOST");
// you should see DOCKER_HOST on the last line!
Console.WriteLine("> see has value: 2375 at the end?");
Console.WriteLine(concatAll.Result);
}
}
第二种解决方案是从ShellStream
获取SshClient
。这使您有机会像读文件一样非常相似地读取和写入字节
在我们建立连接和流之后,我们阅读所有要阅读的内容。一旦流为空,我们通过写入流发送第一个命令。然后我们等待一段流来获取要读取的数据,然后再次从流中读取,直到流为空。那时我们可以开始下一个命令,冲洗并重复,直到完成所有命令。
static void SolutionTwo(ConnectionInfo connection)
{
using (SshClient client = new SshClient(connection))
{
client.ErrorOccurred += (e, s) =>
{
Debug.WriteLine(s.Exception);
};
client.Connect();
using (var stream = client.CreateShellStream("dumb", 512, 96, 800, 600, 8191))
{
stream.ErrorOccurred += (e, s) =>
{
Debug.WriteLine(s.Exception);
};
// read welcome message
Console.WriteLine(ReadFromStream(stream));
// first command and read its output
WriteToStream(stream, "uname\n");
Console.WriteLine(ReadFromStream(stream));
// second and output
WriteToStream(stream, "df\n");
Console.WriteLine(ReadFromStream(stream));
// third and output
WriteToStream(stream, "ps aux\n");
Console.WriteLine(ReadFromStream(stream));
}
Console.ForegroundColor = ConsoleColor.Green;
Console.WriteLine(" >>>>>we are all done");
Console.ForegroundColor = ConsoleColor.White;
}
}
static void WriteToStream(ShellStream stream, string command)
{
stream.Write(command);
}
static StringBuilder ReadFromStream(ShellStream stream)
{
var result = new StringBuilder();
// there seems to be a timing/concurrency issue
// which I only could fix with using this
// useless Sleep calls
Thread.Sleep(500);
// wait for the Stream to have data
while (stream.Length == 0)
{
// yes, I know ...
Thread.Sleep(500);
}
// let's read!
string line;
while ((line = stream.ReadLine()) != null)
{
result.AppendLine(line);
}
return result;
}
正如您在ReadFromStream
方法中注意到的那样,有一些可疑的黑客行为。我努力从流中读取可靠性。在我最初的尝试中,我使用了DataReceived
事件,但无论我如何尝试,它都可以用于几行甚至是字符,或者它根本不起作用。最后,我回到了一个令人讨厌的Thread.Sleep调用,它始终可靠。也许它是库中的一个错误或我本地设置中的某些东西,但我放弃了。