如何在Erlang中使用ssh_connection:exec?

gex*_*tra 5 erlang

这是一个有趣的情况,侧重于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程序的示例.作为脚本,您可以运行简单的睡眠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).
Run Code Online (Sandbox Code Playgroud)

远程脚本:

#!/bin/sh
sleep 10
Run Code Online (Sandbox Code Playgroud)

小智 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.
Run Code Online (Sandbox Code Playgroud)

您应该收到命令输出和其他 ssh 消息,最后是一条“关闭”消息,这是 ssh 命令已正确完成的信号。