【问题标题】:Apache Mina SSHD and Jsch: Input stream is always 0Apache Mina SSHD 和 Jsch:输入流始终为 0
【发布时间】:2016-12-10 07:22:30
【问题描述】:

我正在使用 Jsch 库测试简单的 Apache Mina SSHD 服务器。 Junit 测试如下:

package com.ssh;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import org.apache.sshd.SshServer;
import org.apache.sshd.common.NamedFactory;
import org.apache.sshd.server.PasswordAuthenticator;
import org.apache.sshd.server.UserAuth;
import org.apache.sshd.server.auth.UserAuthPassword;
import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider;
import org.apache.sshd.server.session.ServerSession;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;

import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelExec;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;
import com.ssh.util.EchoShellFactory;

public class SshServiceTest {

    @Rule
    public TemporaryFolder testFolder = new TemporaryFolder();

    private static final String USERNAME = "username";

    private static final String PASSWORD = "password";

    private static final String HOSTNAME = "localhost";

    private SshServer sshd;

    @Before
    public void prepare() throws IOException {
        setupSSHServer();
    }

    private void setupSSHServer() throws IOException {
        sshd = SshServer.setUpDefaultServer();
        sshd.setPort(22);
        sshd.setKeyPairProvider(
                new SimpleGeneratorHostKeyProvider(testFolder.newFile("hostkey.ser").getAbsolutePath()));

        List<NamedFactory<UserAuth>> userAuthFactories = new ArrayList<NamedFactory<UserAuth>>();
        userAuthFactories.add(new UserAuthPassword.Factory());
        sshd.setUserAuthFactories(userAuthFactories);

        sshd.setPasswordAuthenticator(new PasswordAuthenticator() {
            public boolean authenticate(String username, String password, ServerSession session) {
                return USERNAME.equals(username) && PASSWORD.equals(password);
            }
        });

        sshd.setShellFactory(new EchoShellFactory()); 
        sshd.start();
    }

    @Test
    public void testConnection() throws Exception {
        System.out.println("test started");

        java.util.Properties config = new java.util.Properties();
        config.put("StrictHostKeyChecking", "no");
        JSch jsch = new JSch();
        Session session = jsch.getSession(USERNAME, HOSTNAME, 22);
        session.setPassword(PASSWORD);
        session.setConfig(config);
        session.connect();
        System.out.println("Connected");

        Channel channel = session.openChannel("exec");
        ((ChannelExec) channel).setCommand("pwd");

        ((ChannelExec) channel).setErrStream(System.err);
        InputStream in = channel.getInputStream();

        channel.connect();

        byte[] tmp = new byte[1024];
        while (true) {
            while (in.available() > 0) {
                int i = in.read(tmp, 0, 1024);
                if (i < 0)
                    break;
                System.out.print(new String(tmp, 0, i));
            }
            if (channel.isClosed()) {
                System.out.println("exit-status: " + channel.getExitStatus());
                break;
            }
            try {
                Thread.sleep(1000);
            } catch (Exception ee) {
            }
        }

        channel.disconnect();
        session.disconnect();
        System.out.println("DONE");

    }

    @After
    public void cleanup() throws InterruptedException {
        try {
            sshd.stop(true);
        } catch (Exception e) {
            System.out.println(e);
        }
    }
}

我的外壳工厂看起来像:

package com.ssh.util;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.InterruptedIOException;
import java.io.OutputStream;

import org.apache.sshd.common.Factory;
import org.apache.sshd.server.Command;
import org.apache.sshd.server.Environment;
import org.apache.sshd.server.ExitCallback;

public class EchoShellFactory implements Factory<Command> {

    public Command create() {
        return new EchoShell();
    }

    public static class EchoShell implements Command, Runnable {

        private InputStream in;
        private OutputStream out;
        private OutputStream err;
        private ExitCallback callback;
        private Environment environment;
        private Thread thread;

        public InputStream getIn() {
            return in;
        }

        public OutputStream getOut() {
            return out;
        }

        public OutputStream getErr() {
            return err;
        }

        public Environment getEnvironment() {
            return environment;
        }

        public void setInputStream(InputStream in) {
            this.in = in;
        }

        public void setOutputStream(OutputStream out) {
            this.out = out;
        }

        public void setErrorStream(OutputStream err) {
            this.err = err;
        }

        public void setExitCallback(ExitCallback callback) {
            this.callback = callback;
        }

        public void start(Environment env) throws IOException {
            environment = env;
            thread = new Thread(this, "EchoShell");
            thread.start();
        }

        public void destroy() {
            thread.interrupt();
        }

        public void run() {
            BufferedReader r = new BufferedReader(new InputStreamReader(in));
            try {
                for (;;) {
                    String s = r.readLine();
                    if (s == null) {
                        return;
                    }
                    out.write(("executed " + s + "\r\n").getBytes());
                    out.flush();
                    if ("exit".equals(s)) {
                        return;
                    }
                }
            } catch (InterruptedIOException e) {
                // Ignore
            } catch (Exception e) {
                System.out.println("Error executing EchoShell...");
            } finally {
                if (r != null) {
                    try {
                        r.close();
                    } catch (IOException e) {
                        // ignore
                    }
                }
                callback.onExit(0);
            }
        }
    }
}

在这种情况下,in.available() 的值始终为“0”,而 look 将永远运行。我必须手动停止该过程。当 SSHD 服务器启动时,我可以通过 putty 连接到它并执行虚拟命令。只有当我尝试使用 Jsch lib 连接到此服务器时,如上所示的输入流始终为 0。我搜索了很多地方,但找不到什么问题。如果您对如何使其工作有任何想法,请告诉我。

提前致谢。

【问题讨论】:

    标签: java inputstream jsch sshd apache-mina


    【解决方案1】:

    我解决了这个问题。因为“exec”模式不是交互式的,所以程序认为执行没​​有完成。所以你需要使用“shell”模式而不是“exec”,但需要在命令后添加“exit”或“quit”命令来结束交互。

    【讨论】:

      猜你喜欢
      • 2013-06-20
      • 2015-09-02
      • 2019-05-27
      • 1970-01-01
      • 2015-07-01
      • 2013-10-14
      • 2016-04-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多