1

我已经使用 Trilead 和 Jsch 作为 Hg 的 SSH 客户端,现在我正在尝试使用 SSHJ,因为它似乎提供了更现代的密钥支持。草图代码如下

SSHClient client = createClientAndAuthenticate();
Session session = client.startSession();
Command cmd = session.exec(command); // command usually is "hg -R /path/to/hg/repository serve --stdio"

startThreadToCopyInputStream(cmd.getOutputStream());

startThreadToCopyOutputStream(cmd.getInputStream());
startThreadToCopyOutputStream(cmd.getErrorStream());

cmd.join(); // here it hangs endlessly

startThreadToCopyInputStream方法将所有字节从本地 Hg 进程复制到cmd.getOutputStream()然后完成输入流。但与 Trilead 和 JSch 不同的是cmd.getInputStream(),它们cmd.getErrorStream()始终保持开放状态。

我现在将代码更改为:

SSHClient client = createClientAndAuthenticate();
Session session = client.startSession();
Command cmd = session.exec(command); // command usually is "hg -R /path/to/hg/repository serve --stdio"

startThreadToCopyInputStream(cmd.getOutputStream());

startThreadToCopyOutputStream(cmd.getInputStream());
startThreadToCopyOutputStream(cmd.getErrorStream());

waitUntilInputStreamIsClosed();
cmd.close();

这在 90% 的情况下都可以正常工作,但有时 Hg 会抱怨服务器提前关闭了连接。cmd.close()由于服务器进程已完成,我应该如何知道何时可以调用?

4

1 回答 1

0

看起来这是 SSHJ 中的一个错误(见票 143)。解决方法是不cmd.getOutputStream()直接使用,而是:

OutputStream cmdOutputStream = new FilterOutputStream(cmd.getOutputStream()) {
    @Override
    public void close() throws IOException {
        try {
            super.close();
        }
        finally {
            client.getTransport().write(new SSHPacket(Message.CHANNEL_EOF).putUInt32(session.getRecipient()));
        }
    }
};

在传递给startThreadToCopyInputStream(cmdOutputStream);.

于 2017-11-09T14:52:40.073 回答