如何使用Java在远程系统上运行SSH命令?

38

我对这种Java应用程序很陌生,正在寻找一些示例代码,以使用Java编程语言连接到远程服务器,执行命令,并获取输出结果。


1
我在这里发布了一些可能有用的代码:https://dev59.com/uXE95IYBdhLWcg3wN7Ov - Charity Leschinski
这个回答解决了你的问题吗?Java的SSH库 - EdChum
6个回答

24

请查看 Runtime.exec() Javadoc文档。

Process p = Runtime.getRuntime().exec("ssh myhost");
PrintStream out = new PrintStream(p.getOutputStream());
BufferedReader in = new BufferedReader(new InputStreamReader(p.getInputStream()));

out.println("ls -l /home/me");
while (in.ready()) {
  String s = in.readLine();
  System.out.println(s);
}
out.println("exit");

p.waitFor();

3
@Zubair - 给出-1的人并没有解释他的观点。这个解决方案是可行的,因为它非常简单。虽然它不是“纯Java”,但这是一个缺点,但如果你在Linux上,除非使用第三方库,否则你不能使它更简单。 - bobah
1
你会如何处理密码? - mors
@mors - #1密钥认证,#2-与子进程的任何其他输入/输出相同 - bobah
嗨Bobah,我没有看到任何IP地址、用户名、密码...你能告诉我ssh myhost是什么吗?它是IP地址吗? - ChanGan
@ChanGan - "myhost" 是 IP 地址,"ssh" 是可执行文件的名称。 - bobah
显示剩余4条评论

13

JSch是SSH2的纯Java实现,帮助您在远程机器上运行命令。

您可以在这里找到它,这里有一些示例

您可以使用exec.java


9
我使用基于JSch库的解决方案:
import com.google.common.io.CharStreams
import com.jcraft.jsch.ChannelExec
import com.jcraft.jsch.JSch
import com.jcraft.jsch.JSchException
import com.jcraft.jsch.Session

import static java.util.Arrays.asList

class RunCommandViaSsh {

    private static final String SSH_HOST = "test.domain.com"
    private static final String SSH_LOGIN = "username"
    private static final String SSH_PASSWORD = "password"

    public static void main() {
        System.out.println(runCommand("pwd"))
        System.out.println(runCommand("ls -la"));
    }

    private static List<String> runCommand(String command) {
        Session session = setupSshSession();
        session.connect();

        ChannelExec channel = (ChannelExec) session.openChannel("exec");
        try {
            channel.setCommand(command);
            channel.setInputStream(null);
            InputStream output = channel.getInputStream();
            channel.connect();

            String result = CharStreams.toString(new InputStreamReader(output));
            return asList(result.split("\n"));

        } catch (JSchException | IOException e) {
            closeConnection(channel, session)
            throw new RuntimeException(e)

        } finally {
            closeConnection(channel, session)
        }
    }

    private static Session setupSshSession() {
        Session session = new JSch().getSession(SSH_LOGIN, SSH_HOST, 22);
        session.setPassword(SSH_PASSWORD);
        session.setConfig("PreferredAuthentications", "publickey,keyboard-interactive,password");
        session.setConfig("StrictHostKeyChecking", "no"); // disable check for RSA key
        return session;
    }

    private static void closeConnection(ChannelExec channel, Session session) {
        try {
            channel.disconnect()
        } catch (Exception ignored) {
        }
        session.disconnect()
    }
}

应该添加jsch .jar文件或相应的maven依赖。 - Shoaeb
你的回答非常有用,但代码中存在一些错误。由于主题紧密相关,对于新手来说不可能在此处附上编辑后的类,因此请在github上查看https://github.com/menkom/JavaSshClient/blob/main/SshClient.java。几乎相同的内容也可以在官方页面上找到,展示了使用方式http://www.jcraft.com/jsch/examples/Exec.java.html,但我的类可直接使用,无需了解实现细节。 - Mike Menko
我们能否运行 tail -f 命令并持续打印日志? - Awanish Kumar

7

以下是在Java中进行SSH的最简单方法。下载下面链接中的任何文件并解压缩,然后从提取的文件中添加jar文件,并将其添加到项目的构建路径中。 http://www.ganymed.ethz.ch/ssh2/ 然后使用以下方法。

public void SSHClient(String serverIp,String command, String usernameString,String password) throws IOException{
        System.out.println("inside the ssh function");
        try
        {
            Connection conn = new Connection(serverIp);
            conn.connect();
            boolean isAuthenticated = conn.authenticateWithPassword(usernameString, password);
            if (isAuthenticated == false)
                throw new IOException("Authentication failed.");        
            ch.ethz.ssh2.Session sess = conn.openSession();
            sess.execCommand(command);  
            InputStream stdout = new StreamGobbler(sess.getStdout());
            BufferedReader br = new BufferedReader(new InputStreamReader(stdout));
            System.out.println("the output of the command is");
            while (true)
            {
                String line = br.readLine();
                if (line == null)
                    break;
                System.out.println(line);
            }
            System.out.println("ExitCode: " + sess.getExitStatus());
            sess.close();
            conn.close();
        }
        catch (IOException e)
        {
            e.printStackTrace(System.err);

        }
    }

这可以在Spring Boot中完成吗? - Youssef Boudaya

3
您可以查看这个基于Java的远程命令执行框架,包括通过SSH:https://github.com/jkovacic/remote-exec。它依赖于两个开源SSH库,JSch(对于此实现,甚至支持ECDSA身份验证)或Ganymed(这两个库中的一个就足够了)。乍一看,它可能看起来有点复杂,您将不得不准备大量与SSH相关的类(提供服务器和用户详细信息,指定加密详细信息,提供OpenSSH兼容的私钥等等,但是SSH本身也非常复杂)。另一方面,模块化设计允许简单地包含更多SSH库,轻松实现其他命令输出处理或甚至交互式类等。

1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接