erlang 实现了 对 ssh 的支持,本文只讲述我自己对所理解的ssh 模块的部分理解,如果错误,烦请指出,万分感谢。
使用 ssh 模块,先要启动 ssh 功能: ssh:start()。erlang 的 ssh 分为 client 和 server 两部分。可以起一个 erlang 节点用来支持 server,也可以使用 Linux 下默认的 22 号端口来支持 server(已经启动了 sshd 服务)。如果 起一个 erlang 节点作为 server的话,可以自定义很多特征,比如 端口改变,IP地址改变,加解密算法,记录日志函数,密钥,目录等等。使用 ssh:daemon() 函数进行启动。不过我没怎么研究过这个模式。
还可以 直接连接 22 号端口,server 部分由 sshd服务提供。
client 就用一个 erlang 节点来处理。在A机器上面启动一个 erlang 节点,当成 ssh 的客户端,连接 B机器的 22 号端口,用来执行 B 机器上面的 shell 命令。A机器的操作步骤如下:
1, ssh:start(). 启动 ssh 模块的功能。
2,获取 一个 ssh 连接。这个 Ref 指针是用来表示一个 ssh 连接的。
{ok,Ref}= ssh:connect("192.168.217.135",22,[]).
3,生成一个 ssh_channel_id() 。ssh_channel_id 是一个信道的标识,我们后面要往这个信道发送shell 命令。下面的 1000 表示 超时时间是 1000 毫秒。
{ok,ChannelId} = ssh_connection:session_channel(Ref,1000).
4,设置 该ssh 连接的 该信道 的通信为 需要回复,如果不设置这个,那么你的 erlang 进程将会一直卡在 执行 shell 命令的那个地方,无法退出。个人觉得原因是 该ssh_channel_id 不可用。因为 exec 函数在执行 shell 命令成功之后,将会关闭这个 ssh_channel_id 。
sh_connection:reply_request(Ref,true,success,ChannelId). 这个设置 返回值的 状态是 wanted 。要设置成这个才不会 卡死。
5,执行 远程命令
ssh_connection:exec(Ref,ChannelId,"/home/start.sh",1000).
需要注意的是,exec 函数执行成功之后,将会关闭 这个ChannelId,此时如果执行 ssh_connection:send_eof(Ref, ChannelId) 来关闭这个ChannelId 将会报错,所以下次你要调用 exec 函数的时候,记得先 执行 第3 步,生成一个 新的 ssh_channel_id ,然后执行 第4 步,将这个新的 ssh_channel_id 置为 需要回复,然后利用该 新的 ssh_channel_id 执行 第5 步。
这里还残留了一些问题,比如如何让 B机器上执行的 脚本的结果返回给 A机器的 erlang 节点,如何在 B机器上面启动节点处理 ssh server的消息,留待以后再深入研究。