停止 Erlang SSH 通道时出现问题
注意:我将在此处使用 ssh_sftp
通道作为示例,但我注意到使用不同通道时会出现相同的行为。
启动通道后:(
{ok, ChannelPid} = ssh_sftp:start_channel(State#state.cm),
其中 cm 是我的连接管理器),我正在通过通道执行操作。说:
ssh_sftp:write_file(ChannelPid, FilePath, Content),
然后,我要停止通道:
ssh_sftp:stop_channel(ChannelPid),
因为据我所知,通道是作为 gen_server
实现的,所以我期望请求按顺序排列。
好吧,经过一番跟踪,我注意到在文件写入完成并且操作结果通过通道发送之前,通道以某种方式停止了。结论是,响应不会通过通道发送,因为通道不再存在。
如果我没有明确停止通道,一切都会正常工作,并且文件写入(或通过通道执行的任何其他操作)都会正确完成。但我宁愿避免留下开放的渠道。另一方面,我宁愿避免实现自己的接收处理程序来等待结果,然后才能停止通道。
我可能在这里遗漏了一些微不足道的东西。您知道为什么会发生这种情况和/或我可以解决它吗?
我再说一遍,ssh_sftp
只是一个示例。我正在使用自己的通道,使用 Erlang SSH 应用程序中的现有通道作为模板来实现。
NOTE: I'll use the ssh_sftp
channel as an example here, but I've noticed the same behaviour when using different channels.
After starting a channel:
{ok, ChannelPid} = ssh_sftp:start_channel(State#state.cm),
(where cm is my Connection Manager), I'm performing an operation through the channel. Say:
ssh_sftp:write_file(ChannelPid, FilePath, Content),
Then, I'm stopping the channel:
ssh_sftp:stop_channel(ChannelPid),
Since, as far as I know, the channel is implemented as a gen_server
, I was expecting the requests to be sequentialized.
Well, after a bit of tracing, I've noticed that the channel is somehow stopped before the file write is completed and the result of the operation is sent through the channel. As a conclusion, the response is not sent through the channel, since the channel doesn't exist anymore.
If I don't stop the channel explicitely, everything works fine and the file write (or any other operation performed through the channel) is completed correctly. But I would prefer to avoid to leave open channels. On the other hand, I would prefer to avoid implementing my own receive handler to wait for the result before the channel can be stopped.
I'm probably missing something trivial here. Do you have any idea why this is happening and/or I could fix it?
I repeat, the ssh_sftp
is just an example. I'm using my own channels, implemented using the existing channels in the Erlang SSH application as a template.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
正如您在 ssh_sftp.erl 中看到的在 5 秒超时后使用 exit(Pid, Kill) 强制终止通道,这会中断进程,无论它是否正在处理某些内容。
来自 erlang man 的相关引用:
As you can see in ssh_sftp.erl it forcefully kills channel after 5 sec timeout with exit(Pid, kill) which interrupts the process regardless of whether it's processing something or not.
Related quote from erlang man:
我对 ssh_connection:exec/4 也有类似的问题。问题是这些 ssh 同级模块(ssh_connection、ssh_sftp 等)似乎都是异步行为,因此关闭 ssh 本身的通道将关闭正在进行的操作。
选项是:
1) 不要关闭连接:这可能会导致资源泄漏。我的问题的目的此处
2)之后sftp引入了一个监视功能,通过监视您在远程服务器上传输的文件来等待(校验和检查)。这可以基于 ssh_connection:exec 并轮询您正在传输的文件。一旦校验和符合您的预期,您就可以释放主模块
I had a similar issue with ssh_connection:exec/4. The problem is that these ssh sibling modules ( ssh_connection, ssh_sftp, etc) all appear to behave asynchronously, therefore a closure of channel of ssh itself will shut down the ongoing action.
The options are:
1) do not close the connection : this may lead to leak of resources. Purpose of my question here
2) After the sftp, introduce a monitoring function that waits by monitoring on the file you are transfering at the remote server ( checksum check ). This can be based on ssh_connection:exec and poll on the file you are transferring. Once the checksum matches what you expect, you can free the main module