C# 如何使用.net ssh sshclient保持会话正常进行

C# 如何使用.net ssh sshclient保持会话正常进行,c#,ssh,C#,Ssh,我在ssh client for.Net中使用上述命令,但它不保留在后面两个命令中执行导出的第一个命令的状态 如果我手动使用ssh并执行这3个命令,它将按照我的预期工作,但是上面的c代码似乎忘记了后续命令中的导出。我假设您正在使用库。在下面的解决方案中,我使用了,它也可以作为NuGet包提供 有两种可能的解决方案来实现这一点。第一种方法是将要运行的命令组合到一个RunCommand中。每次调用RunCommand时,它都会启动一个新的shell,并且会忘记您执行的任何环境设置。通过将命令与操作符

我在ssh client for.Net中使用上述命令,但它不保留在后面两个命令中执行导出的第一个命令的状态


如果我手动使用ssh并执行这3个命令,它将按照我的预期工作,但是上面的c代码似乎忘记了后续命令中的导出。

我假设您正在使用库。在下面的解决方案中,我使用了,它也可以作为NuGet包提供

有两种可能的解决方案来实现这一点。第一种方法是将要运行的命令组合到一个RunCommand中。每次调用RunCommand时,它都会启动一个新的shell,并且会忘记您执行的任何环境设置。通过将命令与操作符链接,可以实现所有命令都可以在同一个Shell中执行

SshClient client;
var sethost = client.RunCommand("export DOCKER_HOST=:2375");
var infohost = client.RunCommand("docker info");
var ps = client.RunCommand("docker ps");
第二种解决方案是从
SshClient
获取
ShellStream
。这使您有机会像读取文件一样读取和写入字节。
在我们建立了连接和流之后,我们阅读了所有需要阅读的内容。一旦流为空,我们通过写入流来发送第一个命令。然后,我们等待流获取要读取的数据,然后继续从流中再次读取,直到流为空。这时我们可以开始下一个命令,冲洗并重复,直到所有命令都完成

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);
    }
}

正如您在
ReadFromStream
方法中注意到的,存在一些可疑的黑客行为。我费了很大的劲才从小溪里读到可靠的东西。在我最初的尝试中,我使用了
DataReceived
事件,但无论我如何尝试,它要么在几行甚至几字符内都有效,要么根本不起作用。最后,我又回到了一个令人讨厌的问题上。睡眠电话一直都很可靠。也许是库中的一个bug,或者是我本地设置中的一些东西,但我放弃了

我假设您正在使用库。在下面的解决方案中,我使用了,它也可以作为NuGet包提供

有两种可能的解决方案来实现这一点。第一种方法是将要运行的命令组合到一个RunCommand中。每次调用RunCommand时,它都会启动一个新的shell,并且会忘记您执行的任何环境设置。通过将命令与操作符链接,可以实现所有命令都可以在同一个Shell中执行

SshClient client;
var sethost = client.RunCommand("export DOCKER_HOST=:2375");
var infohost = client.RunCommand("docker info");
var ps = client.RunCommand("docker ps");
第二种解决方案是从
SshClient
获取
ShellStream
。这使您有机会像读取文件一样读取和写入字节。
在我们建立了连接和流之后,我们阅读了所有需要阅读的内容。一旦流为空,我们通过写入流来发送第一个命令。然后,我们等待流获取要读取的数据,然后继续从流中再次读取,直到流为空。这时我们可以开始下一个命令,冲洗并重复,直到所有命令都完成

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);
    }
}

正如您在
ReadFromStream
方法中注意到的,存在一些可疑的黑客行为。我费了很大的劲才从小溪里读到可靠的东西。在我最初的尝试中,我使用了
DataReceived
事件,但无论我如何尝试,它要么在几行甚至几字符内都有效,要么根本不起作用。最后,我又回到了一个令人讨厌的问题上。睡眠电话一直都很可靠。也许是库中的一个bug,或者是我本地设置中的一些东西,但我放弃了

如果这是您仅有的三个命令,您不能&&t它们,例如:
export DOCKER\u HOST=:2375&&DOCKER info&&DOCKER ps
,因此您只需调用一次
RunCommand
即可添加更多命令,这也取决于已运行的导出。我只是不明白run命令是否每次都像打开一个新的bash如果这是你仅有的三个命令,你不能这样做:
export-DOCKER\u-HOST=:2375&&DOCKER-info&&DOCKER-ps
所以你只需调用一次
RunCommand
就会添加更多的命令,这也取决于导出是否已经运行。我只是不明白run命令是否每次都像打开一个新的bash