5

这是一个有趣的情况,主要关注 erlang ssh 模块的行为。我花了几个小时来解决一个问题,结果证明 Erlang ssh_connection * exec/4 * 函数是异步操作的。

如果您发出ssh_connection:exec/4函数来运行需要几秒钟才能完成的脚本,然后在您的 erlang 程序中关闭 ssh 连接,脚本执行将终止。我的期望是 ssh_connection:exec 将是同步的而不是异步的。

因为完成 ssh_connection:exec 调用的远程脚本的时间是未知的,所以我选择不发出闭包ssh:close()。我想了解这样做的后果:

  • gc 会在某个时候清除它吗?
  • 它会在整个节点存在期间一直保持开放吗?
  • 有没有办法让 ssh_connection:exec 同步,我相信它应该是。

这是我用来验证此问题的测试 erl 程序的示例。作为脚本,您可以运行一个简单的 sleep 10(睡眠 10 秒)来模拟运行缓慢的程序。

-module(testssh).
-export([test/5]).

test (ServerName, Port, Command, User, Password) ->

    crypto:start(),
    ssh:start(),
    {ok, SshConnectionRef}                  = ssh:connect(ServerName, Port, [ {user, User}, {password, Password} , {silently_accept_hosts, true} ], 60000  ),
    {ok, SshConnectionChannelRef}           = ssh_connection:session_channel(SshConnectionRef, 60000),
    Status                                  = ssh_connection:exec(SshConnectionRef, SshConnectionChannelRef, Command, 60000),
    ssh:close(SshConnectionRef).

远程脚本:

#!/bin/sh
sleep 10
4

1 回答 1

4

我自己从来不需要使用 ssh 应用程序,但你应该读错了,文档中很清楚结果将作为消息传递给调用者:

[...] 根据以下模式,结果将是几条消息。请注意,最后一条消息将是一条通道关闭消息,因为 exec 请求是一次性执行,它在完成时关闭通道[...]

http://www.erlang.org/doc/man/ssh_connection.html#exec-4

因此,在您调用 ssh_connection:exec/4 之后,使用如下循环进行测试:

wait_for_response(ConnectionRef) ->
    receive
            {ssh_cm, ConnectionRef, Msg} ->
                    case Msg of
                            {closed, _ChannelId} ->
                                    io:format("Done");
                            _ ->
                                    io:format("Got: ~p", [Msg]),
                                    wait_for_response(ConnectionRef)
                    end
    end.

您应该会收到命令输出和其他 ssh 消息,最后是“关闭”消息,表明 ssh 命令已正确完成。

于 2013-06-07T16:27:33.027 回答