遇到一个需要通过java代码对远程Linux系统进行远程操作的场景,其中包括远程执行命令、上传文件、下载文件。
一、maven依赖
<dependency> <groupId>com.jcraft</groupId> <artifactId>jsch</artifactId> <version>0.1.53</version> </dependency>
二、yml配置
desensitization: server: ip: xxx #IP地址 user: root #登录用户名 password: xxx #登录密码 port: 22 #远程连接端口 path: /root/test_data/ #对应处理的目录
三、配置类编写
import com.xxx.fileupload.exception.BizException; import com.xxx.fileupload.exception.CommonUtilEnum; import com.jcraft.jsch.JSch; import com.jcraft.jsch.JSchException; import com.jcraft.jsch.Session; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; /** * @description: ssh远程连接配置类 * @author ZXS * @date 2022/11/8 9:57 * @version 1.0 */ @Configuration public class JSchSessionConfig { //指定的服务器地址 @Value("${desensitization.server.ip}") private String ip; //用户名 @Value("${desensitization.server.user}") private String user; //密码 @Value("${desensitization.server.password}") private String password; //服务器端口 默认22 @Value("${desensitization.server.port}") private String port; /** * @description: 注入一个bean,jsch.Session * @param: * @return: com.jcraft.jsch.Session * @author ZXS * @date: 2022/11/8 9:58 */ @Bean public Session registSession(){ Session session; try { JSch jSch = new JSch(); //设置session相关配置信息 session = jSch.getSession(user, ip, Integer.valueOf(port)); session.setPassword(password); //设置第一次登陆的时候提示,可选值:(ask | yes | no) session.setConfig("StrictHostKeyChecking", "no"); } catch (JSchException e) { throw new BizException(CommonUtilEnum.FILE_DOWNLOAD_FAIL); } return session; } }
四、组件工具类的编写
import com.xxx.fileupload.exception.BizException; import com.xxx.fileupload.exception.CommonUtilEnum; import com.jcraft.jsch.*; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import javax.annotation.Resource; import java.io.*; /** * @description: ssh远程连接工具类 * @author ZXS * @date 2022/9/28 17:11 * @version 1.0 */ @Component @Slf4j public class SshRemoteComponent { private ThreadLocal<Session> connContainer = new ThreadLocal<>(); @Resource private Session session; //上传文件到脱敏服务器的指定目录 自行修改 @Value("${desensitization.server.path}") private String path; /** * @description: 根据端口号创建ssh远程连接 * @param: port 端口号 * @return: com.jcraft.jsch.Session * @author ZXS * @date: 2022/9/28 15:57 */ public Session createConnection(){ try { session.connect(30000); connContainer.set(session); } catch (JSchException e) { throw new BizException(CommonUtilEnum.CONN_FAIL); } return connContainer.get(); } /** * @description: 关闭ssh远程连接 * @param: * @return: void * @author ZXS * @date: 2022/9/28 15:58 */ public void closeConnection(){ Session session=connContainer.get(); try { if(session != null){ session.disconnect(); } } catch (Exception e) { throw new BizException(CommonUtilEnum.CONN_CLOSE_FAIL); }finally { connContainer.remove(); } } /** * @description: ssh通过sftp上传文件 * @param: session,bytes文件字节流,fileName文件名,resultEncoding 返回结果的字符集编码 * @return: java.lang.String 执行返回结果 * @author ZXS * @date: 2022/9/30 10:02 */ public Boolean sshSftpUpload(Session session, byte[] bytes,String fileName) throws Exception{ //上传文件到指定服务器的指定目录 自行修改 //String path = "/root/test_data/"; Channel channel = null; OutputStream outstream = null; Boolean flag = true; try { //创建sftp通信通道 channel = session.openChannel("sftp"); channel.connect(1000); ChannelSftp sftp = (ChannelSftp) channel; //进入服务器指定的文件夹 sftp.cd(path); //列出服务器指定的文件列表 /*Vector v = sftp.ls("*"); for(int i=0;i<v.size();i++){ System.out.println(v.get(i)); }*/ outstream = sftp.put(fileName); outstream.write(bytes); } catch (Exception e) { e.printStackTrace(); flag = false; } finally { if(outstream != null){ outstream.flush(); outstream.close(); } if(session != null){ closeConnection(); } if(channel != null){ channel.disconnect(); } } return flag; } /** * @description: ssh通过sftp下载文件 * @param: session,fileName文件名,filePath 文件下载保存路径 * @return: java.lang.String 执行返回结果 * @author ZXS * @date: 2022/9/30 10:03 */ public Boolean sshSftpDownload(Session session, String fileName, String filePath) throws Exception{ Channel channel = null; InputStream inputStream = null; FileOutputStream fileOutputStream; Boolean flag = true; try { //创建sftp通信通道 channel = session.openChannel("sftp"); channel.connect(1000); ChannelSftp sftp = (ChannelSftp) channel; //进入服务器指定的文件夹 sftp.cd(path); inputStream = sftp.get(fileName); BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream); fileOutputStream = new FileOutputStream(filePath+"/"+fileName); BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(fileOutputStream); byte[] buf = new byte[4096]; int length = bufferedInputStream.read(buf); while (-1 != length){ bufferedOutputStream.write(buf,0,length); length = bufferedInputStream.read(buf); } bufferedInputStream.close(); bufferedOutputStream.close(); } catch (Exception e) { e.printStackTrace(); flag = false; } finally { if(inputStream != null){ inputStream.close(); } if(session != null){ closeConnection(); } if(channel != null){ channel.disconnect(); } } return flag; } /** * @description: 远程执行单条Linux命令 * @param: session,command命令字符串 * @return: java.lang.String * @author ZXS * @date: 2022/9/28 16:34 */ public Boolean execCommand(Session session, String command){ //默认方式,执行单句命令 ChannelExec channelExec; Boolean flag = true; try { channelExec = (ChannelExec) session.openChannel("exec"); channelExec.setCommand(command); channelExec.setErrStream(System.err); channelExec.connect(); /** 判断执行结果 **/ InputStream in = channelExec.getInputStream(); byte[] tmp = new byte[1024]; while(true){ while(in.available() > 0){ int i = in.read(tmp,0,1024); if(i < 0) break; log.info("脚本执行过程:"+new String(tmp,0,i)); } //获取执行结果 if(channelExec.isClosed()){ if(in.available() > 0) continue; if(channelExec.getExitStatus() != 0){ //脚本非正常结束,退出吗非零 flag = false; log.info("脚本执行出错"); } break; } try{ Thread.sleep(1000); }catch (Exception e){ log.info(e.getMessage()); } } channelExec.disconnect(); } catch (Exception e) { e.printStackTrace(); flag = false; } return flag; } }
五、使用测试
@SpringBootTest @Slf4j public class TestCase { @Resource private SshRemoteComponent component; @Test public void test(){ Session session = component.createConnection(); component.execCommand(session, "pwd"); component.closeConnection(); } }
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持。