1. 概
念
1.1. JSch
- JSch 是SSH2的一个纯Java实现。它允许你连接到一个 sshd 服务器,使用端口转发,X11转发,文件传输等等。
- 说白了就是以 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(); } } } }