springboot远程登陆服务器并操作相关指令

1. 概

1.1. JSch

  1. JSch 是SSH2的一个纯Java实现。它允许你连接到一个 sshd 服务器,使用端口转发,X11转发,文件传输等等。
  2. 说白了就是以 Java 的方式通过 jsch 连接,来对服务器进行操作。

2. 具体案例

2.1. 使用账号密码登陆并执行指令

2.1.1. 引入依赖

        <dependency>
            <groupId>com.github.mwiede</groupId>
            <artifactId>jsch</artifactId>
            <version>0.2.16</version>
        </dependency>

2.1.2. 远程登陆并执行指令

    @GetMapping("/executeCommand")
    public String executeRemoteCommand() {
        String host = ymlConfig.getHost();
        String username = ymlConfig.getUsername();
        String password = ymlConfig.getPassword();


        System.out.println(System.getProperty("user.name"));
        # 可执行cd,touch,git,/usr/bin/docker-compose -f /data/appBins/basic/docker/docker-compose.yml,mvn,ssh
        # 不能使用别名
#  使用这个是可以执行ssh指令的,但是会一直没有响应,查看ssh指令远程的主机,是可以看到远程登陆的日志。
        String command = "ls;touch aa.txt"; 

        RemoteCommandExecutor executor = new RemoteCommandExecutor();
        return executor.executeRemoteCommand(host, username, password, command);
    }



    /**
     * 这段代码主要用于执行单个命令并返回结果,不支持连续的交互式会话。
     * 使用这个是可以执行ssh指令的,但是会一直没有响应,查看ssh指令远程的主机,是可以看到远程登陆的日志。
     * @param host
     * @param username
     * @param password
     * @param command
     * @return
     */
    public String executeRemoteCommand(String host, String username, String password, String command) {
        JSch jsch = new JSch();
        Session session = null;
        try {
            session = jsch.getSession(username, host, 22);
            session.setConfig("StrictHostKeyChecking", "no");
            session.setPassword(password);
            session.connect();

            ChannelExec channel = (ChannelExec) session.openChannel("exec");
            // 设置环境变量和 Maven 命令
            String preCommand = "export PATH=$PATH:/bin:/usr/bin:/root/apache-maven-3.8.5/bin:/root/.bashrc:/etc/profile;source /root/.bashrc;source /etc/profile && ";
            channel.setCommand(preCommand + command);

            InputStream in = channel.getInputStream();

            // 连接通道
            channel.connect();

            // 读取输出
            BufferedReader reader = new BufferedReader(new InputStreamReader(in));
            StringBuilder output = new StringBuilder();
            String line;
            while ((line = reader.readLine()) != null) {
                output.append(line).append("
");
            }

            // 关闭连接
            channel.disconnect();
            session.disconnect();

            return output.toString();
        } catch (JSchException | java.io.IOException e) {
            e.printStackTrace();
            return "Exception occurred: " + e.getMessage();
        }
    }

2.1.3. 通过跳板主机连接到目标主机,并在目标主机上执行命令

  public void executeRemoteCommand() {
        String jumpHost = "";
        int jumpPort = 22;
        String jumpUser = "root";
        String jumpPassword = "";

        String targetHost = "";
        int targetPort = 22;
        String targetUser = "root";
        String targetPassword = "";

        int forwardedPort = 12345;

        try {
            JSch jsch = new JSch();

            // Establish SSH session with jump host
            Session jumpSession = jsch.getSession(jumpUser, jumpHost, jumpPort);
            jumpSession.setPassword(jumpPassword);
            jumpSession.setConfig("StrictHostKeyChecking", "no");
            jumpSession.connect();

            // Execute a command on the jump host
            ChannelExec jumpChannelExec = (ChannelExec) jumpSession.openChannel("exec");
            jumpChannelExec.setCommand("touch newfile.txt");
            jumpChannelExec.connect();


            // Set up port forwarding for the target host through the jump host
            int assignedPort = jumpSession.setPortForwardingL(forwardedPort, targetHost, targetPort);

            // Establish SSH session with target host through the jump host
            Session targetSession = jsch.getSession(targetUser, "localhost", assignedPort);
            targetSession.setPassword(targetPassword);
            targetSession.setConfig("StrictHostKeyChecking", "no");
            targetSession.connect();

            // Execute a command on the target host
            ChannelExec channelExec = (ChannelExec) targetSession.openChannel("exec");
            channelExec.setCommand("touch newfile.txt");
            channelExec.connect();

            // Display output of the command
            InputStream commandOutput = channelExec.getInputStream();
            BufferedReader reader = new BufferedReader(new InputStreamReader(commandOutput));
            String line;
            while ((line = reader.readLine()) != null) {
                System.out.println(line);
            }

            // Disconnect the channel and sessions
            jumpChannelExec.disconnect();
            channelExec.disconnect();
            targetSession.disconnect();
            jumpSession.disconnect();

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

2.2. 使用私钥登陆并执行指令

2.2.1. 引入依赖

        <dependency>
            <groupId>com.github.mwiede</groupId>
            <artifactId>jsch</artifactId>
            <version>0.2.16</version>
        </dependency>

2.2.2. 远程登陆并执行指令

    /**
     * 使用私钥登陆服务器,并使用服务器相关指令进行操作。
     * @return
     */

    @GetMapping("/usePrivateKey")
    public String usePrivateKeyLogin() {

            String command = "ls"; // The command you want to execute
            String host = ymlConfig.getHost();
            String username = ymlConfig.getUsername();
            String privateKeyPath = ymlConfig.getPrivateKeyPath();

            SSHService sshService = new SSHService(host, username, privateKeyPath);
           sshService.executeCommand(command);
           return "执行完成";
        }



    public class SSHService {
    
        private String host;
        private String username;
        private String privateKeyPath;
    
        public SSHService(String host, String username, String privateKeyPath) {
            this.host = host;
            this.username = username;
            this.privateKeyPath = privateKeyPath;
        }
    
        public void executeCommand(String command) {
            Session session = null;
            Channel channel = null;
    
            try {
                JSch jsch = new JSch();
                jsch.addIdentity(privateKeyPath);
    
                session = jsch.getSession(username, host, 22);
    
                Properties config = new Properties();
                config.put("StrictHostKeyChecking", "no");
                session.setConfig(config);
    
                session.connect();
    
                channel = session.openChannel("exec");
                ((ChannelExec) channel).setCommand(command);
    
                channel.setInputStream(null);
                ((ChannelExec)channel).setErrStream(System.err);
                
                channel.connect();
    
                // Read the output from the remote host
                InputStream input = channel.getInputStream();
                try (BufferedReader reader = new BufferedReader(new InputStreamReader(input))) {
                    String line;
                    while ((line = reader.readLine()) != null) {
                        System.out.println(line);
                    }
                }
    
                channel.disconnect();
                session.disconnect();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (session != null) {
                    session.disconnect();
                }
                if (channel != null) {
                    channel.disconnect();
                }
            }
    }
}