赞
踩
JSch是SSH2的纯Java实现。JSch允许您连接到sshd服务器并使用端口转发,X11转发,文件传输等,并且可以将其功能集成到您自己的Java程序中。
根据远程主机的IP地址,用户名和端口,建立会话(Session)
设置用户信息(包括密码和Userinfo),然后连接session,getSession()只是创建一个session,需要设置必要的认证信息之后,调用connect()才能建立连接。
设置channel上需要远程执行的Shell脚本,连接channel,就可以远程执行该Shell脚本,调用openChannel(String type) 可以在session上打开指定类型的channel。该channel只是被初始化,使用前需要先调用connect()进行连接。
可以读取远程执行Shell脚本的输出,然后依次断开channel和session的连接
实验目标:实现文件上传到服务,服务器下载文件以及执行服务器命令
- <?xml version="1.0" encoding="UTF-8"?>
- <project xmlns="http://maven.apache.org/POM/4.0.0"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
- <parent>
- <artifactId>springboot-demo</artifactId>
- <groupId>com.et</groupId>
- <version>1.0-SNAPSHOT</version>
- </parent>
- <modelVersion>4.0.0</modelVersion>
-
-
- <artifactId>JSch</artifactId>
-
-
- <properties>
- <maven.compiler.source>8</maven.compiler.source>
- <maven.compiler.target>8</maven.compiler.target>
- </properties>
- <dependencies>
-
-
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-web</artifactId>
- </dependency>
-
-
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-autoconfigure</artifactId>
- </dependency>
- <dependency>
- <groupId>org.springframework.boot</groupId>
- <artifactId>spring-boot-starter-test</artifactId>
- <scope>test</scope>
- </dependency>
- <!-- https://mvnrepository.com/artifact/com.jcraft/jsch -->
- <dependency>
- <groupId>com.jcraft</groupId>
- <artifactId>jsch</artifactId>
- <version>0.1.55</version>
- </dependency>
- <dependency>
- <groupId>org.projectlombok</groupId>
- <artifactId>lombok</artifactId>
- </dependency>
- <dependency>
- <groupId>com.alibaba</groupId>
- <artifactId>fastjson</artifactId>
- <version>1.2.78</version>
- </dependency>
- </dependencies>
- </project>

- package com.et.jsch.model;
-
-
- import lombok.Data;
-
-
- @Data
- public class Remote {
- private String host;
- private final int port = 22;
- private String user;
- private String password;
- private final String identity = "~/.ssh/id_rsa";
- private String passphrase;
- }
- package com.et.jsch.util;
-
-
- import com.et.jsch.model.Remote;
- import com.jcraft.jsch.*;
- import lombok.extern.slf4j.Slf4j;
-
-
- import java.io.*;
- import java.nio.file.Files;
- import java.nio.file.Paths;
- import java.util.ArrayList;
- import java.util.List;
- import java.util.function.Function;
-
-
- /**
- * ssh tools
- */
- @Slf4j
- public class JSchUtil {
-
-
- public static final int SESSION_TIMEOUT = 30000;
- public static final int CONNECT_TIMEOUT = 3000;
-
-
- /**
- * get session
- *
- * @param remote ssh server info
- * @return session
- * @throws JSchException /
- */
- public static Session getSession(Remote remote) throws JSchException {
- JSch jSch = new JSch();
- if (Files.exists(Paths.get(remote.getIdentity()))) {
- jSch.addIdentity(remote.getIdentity(), remote.getPassphrase());
- }
- Session session = jSch.getSession(remote.getUser(), remote.getHost(), remote.getPort());
- session.setPassword(remote.getPassword());
- session.setConfig("StrictHostKeyChecking", "no");
- return session;
- }
-
-
- /**
- * excute remote command
- *
- * @param session session
- * @param command command
- * @return /
- * @throws JSchException /
- */
- public static List<String> remoteExecute(Session session, String command) throws JSchException {
- log.debug(">> {}", command);
- List<String> resultLines = new ArrayList<>();
- ChannelExec channel = null;
- try {
- channel = openExecChannel(session);
- channel.setCommand(command);
- InputStream input = channel.getInputStream();
- channel.connect(CONNECT_TIMEOUT);
- try {
- BufferedReader inputReader = new BufferedReader(new InputStreamReader(input));
- String inputLine;
- while ((inputLine = inputReader.readLine()) != null) {
- log.debug(" {}", inputLine);
- resultLines.add(inputLine);
- }
- } finally {
- if (input != null) {
- try {
- input.close();
- } catch (Exception e) {
- log.error("JSch inputStream close error:", e);
- }
- }
- }
- } catch (IOException e) {
- log.error("IOException:", e);
- } finally {
- disconnect(channel);
- }
- return resultLines;
- }
-
-
- /**
- * scp file to remote server
- *
- * @param session session
- * @param source local file
- * @param destination remote target file
- * @return file size
- */
- public static long scpTo(Session session, String source, String destination) {
- FileInputStream fileInputStream = null;
- ChannelExec channel = null;
- try {
- channel = openExecChannel(session);
- OutputStream out = channel.getOutputStream();
- InputStream in = channel.getInputStream();
- boolean ptimestamp = false;
- String command = "scp";
- if (ptimestamp) {
- command += " -p";
- }
- command += " -t " + destination;
- channel.setCommand(command);
- channel.connect(CONNECT_TIMEOUT);
- if (checkAck(in) != 0) {
- return -1;
- }
- File _lfile = new File(source);
- if (ptimestamp) {
- command = "T " + (_lfile.lastModified() / 1000) + " 0";
- // The access time should be sent here,
- // but it is not accessible with JavaAPI ;-<
- command += (" " + (_lfile.lastModified() / 1000) + " 0\n");
- out.write(command.getBytes());
- out.flush();
- if (checkAck(in) != 0) {
- return -1;
- }
- }
- //send "C0644 filesize filename", where filename should not include '/'
- long fileSize = _lfile.length();
- command = "C0644 " + fileSize + " ";
- if (source.lastIndexOf('/') > 0) {
- command += source.substring(source.lastIndexOf('/') + 1);
- } else {
- command += source;
- }
- command += "\n";
- out.write(command.getBytes());
- out.flush();
- if (checkAck(in) != 0) {
- return -1;
- }
- //send content of file
- fileInputStream = new FileInputStream(source);
- byte[] buf = new byte[1024];
- long sum = 0;
- while (true) {
- int len = fileInputStream.read(buf, 0, buf.length);
- if (len <= 0) {
- break;
- }
- out.write(buf, 0, len);
- sum += len;
- }
- //send '\0'
- buf[0] = 0;
- out.write(buf, 0, 1);
- out.flush();
- if (checkAck(in) != 0) {
- return -1;
- }
- return sum;
- } catch (JSchException e) {
- log.error("scp to caught jsch exception, ", e);
- } catch (IOException e) {
- log.error("scp to caught io exception, ", e);
- } catch (Exception e) {
- log.error("scp to error, ", e);
- } finally {
- closeInputStream(fileInputStream);
- disconnect(channel);
- }
- return -1;
- }
-
-
- /**
- * scp remote file to local
- *
- * @param session session
- * @param source remote file
- * @param destination local file
- * @return file size
- */
- public static long scpFrom(Session session, String source, String destination) {
- FileOutputStream fileOutputStream = null;
- ChannelExec channel = null;
- try {
- channel = openExecChannel(session);
- channel.setCommand("scp -f " + source);
- OutputStream out = channel.getOutputStream();
- InputStream in = channel.getInputStream();
- channel.connect();
- byte[] buf = new byte[1024];
- //send '\0'
- buf[0] = 0;
- out.write(buf, 0, 1);
- out.flush();
- while (true) {
- if (checkAck(in) != 'C') {
- break;
- }
- }
- //read '644 '
- in.read(buf, 0, 4);
- long fileSize = 0;
- while (true) {
- if (in.read(buf, 0, 1) < 0) {
- break;
- }
- if (buf[0] == ' ') {
- break;
- }
- fileSize = fileSize * 10L + (long) (buf[0] - '0');
- }
- String file = null;
- for (int i = 0; ; i++) {
- in.read(buf, i, 1);
- if (buf[i] == (byte) 0x0a) {
- file = new String(buf, 0, i);
- break;
- }
- }
- // send '\0'
- buf[0] = 0;
- out.write(buf, 0, 1);
- out.flush();
- // read a content of lfile
- if (Files.isDirectory(Paths.get(destination))) {
- fileOutputStream = new FileOutputStream(destination + File.separator + file);
- } else {
- fileOutputStream = new FileOutputStream(destination);
- }
- long sum = 0;
- while (true) {
- int len = in.read(buf, 0, buf.length);
- if (len <= 0) {
- break;
- }
- sum += len;
- if (len >= fileSize) {
- fileOutputStream.write(buf, 0, (int) fileSize);
- break;
- }
- fileOutputStream.write(buf, 0, len);
- fileSize -= len;
- }
- return sum;
- } catch (JSchException e) {
- log.error("scp to caught jsch exception, ", e);
- } catch (IOException e) {
- log.error("scp to caught io exception, ", e);
- } catch (Exception e) {
- log.error("scp to error, ", e);
- } finally {
- closeOutputStream(fileOutputStream);
- disconnect(channel);
- }
- return -1;
- }
-
-
- /**
- * remote edit
- *
- * @param session session
- * @param source target file
- * @param process edit command collect
- * @return isSuccess
- */
- private static boolean remoteEdit(Session session, String source, Function<List<String>, List<String>> process) {
- InputStream in = null;
- OutputStream out = null;
- try {
- String fileName = source;
- int index = source.lastIndexOf('/');
- if (index >= 0) {
- fileName = source.substring(index + 1);
- }
- //backup source
- remoteExecute(session, String.format("cp %s %s", source, source + ".bak." + System.currentTimeMillis()));
- //scp from remote
- String tmpSource = System.getProperty("java.io.tmpdir") + session.getHost() + "-" + fileName;
- scpFrom(session, source, tmpSource);
- in = new FileInputStream(tmpSource);
- //edit file according function process
- String tmpDestination = tmpSource + ".des";
- out = new FileOutputStream(tmpDestination);
- List<String> inputLines = new ArrayList<>();
- BufferedReader reader = new BufferedReader(new InputStreamReader(in));
- String inputLine = null;
- while ((inputLine = reader.readLine()) != null) {
- inputLines.add(inputLine);
- }
- List<String> outputLines = process.apply(inputLines);
- for (String outputLine : outputLines) {
- out.write((outputLine + "\n").getBytes());
- out.flush();
- }
- //scp to remote
- scpTo(session, tmpDestination, source);
- return true;
- } catch (Exception e) {
- log.error("remote edit error, ", e);
- return false;
- } finally {
- closeInputStream(in);
- closeOutputStream(out);
- }
- }
-
-
- /**
- * update file
- *
- * @param session session
- * @param in file stream
- * @param directory local dir
- * @param fileName FTP server file name:xxx.txt ||xxx.txt.zip
- */
- public static boolean uploadFile(Session session, InputStream in, String directory, String fileName) {
- log.info(">>>>>>>>uploadFile--ftp start>>>>>>>>>>>>>");
- ChannelSftp channel = null;
- try {
- channel = openSftpChannel(session);
- channel.connect(CONNECT_TIMEOUT);
- String[] folders = directory.split("/");
- try {
- for (int i = 0; i < folders.length; i++) {
- if (i == 0 && folders[i].length() == 0) {
- channel.cd("/");
- } else if (folders[i].length() > 0) {
- try {
- channel.cd(folders[i]);
- } catch (SftpException e) {
- channel.mkdir(folders[i]);
- channel.cd(folders[i]);
- }
- }
- }
- } catch (SftpException e) {
- log.error("ftp create file fail" + directory, e);
- return false;
- }
-
-
- try {
- channel.put(in, fileName);
- } catch (SftpException e) {
- log.error("sftp error-->" + e.getMessage(), e);
- return false;
- }
-
-
- log.info(">>>>>>>>uploadFile--ftp upload end>>>>>>>>>>>>>");
- log.info(">>>>>>>>ftp upload dir:{},filename:{}>>>>>>>>>>>>>", directory, fileName);
-
-
- return true;
- } catch (JSchException e) {
- log.error("JSch error-->" + e.getMessage(), e);
- return false;
- } finally {
- closeInputStream(in);
- disconnect(channel);
- }
- }
-
-
-
-
- /**
- *
- *
- * @param channel sftp connect
- * @param directory
- * @param fileName
- * @return
- */
- public static InputStream stream(ChannelSftp channel, String directory, String fileName) {
- try {
- channel.connect(CONNECT_TIMEOUT);
- InputStream inputStream = channel.get(directory + "/" + fileName);
- log.info(">>>>>>>>ftp file directory:{},filename:{}>>>>>>>>>>>>>", directory, fileName);
- return inputStream;
- } catch (SftpException e) {
- log.error("sftp error-->" + e.getMessage());
- return null;
- } catch (JSchException e) {
- log.error("JSch error-->" + e.getMessage());
- return null;
- }
- }
-
-
-
-
- /**
- * ftp delete remote file
- *
- * @param session session
- * @param directory directory
- * @param fileName filename
- * @return is Success
- */
- public static boolean deleteFile(Session session, String directory, String fileName) {
- log.info(">>>>>>>>deleteFile--ftp delete file end>>>>>>>>>>>>>");
- ChannelSftp channel = null;
- try {
- channel = openSftpChannel(session);
- channel.connect(CONNECT_TIMEOUT);
- channel.rm(directory + "/" + fileName);
-
-
- log.info(">>>>>>>>deleteFile--deletefile end>>>>>>>>>>>>>");
- log.info(">>>>>>>>ftp delete file directory:{},filename:{}>>>>>>>>>>>>>", directory, fileName);
- } catch (SftpException e) {
- log.error("ftp create directory fail" + directory);
- return false;
- } catch (JSchException e) {
- log.error("JSch error-->" + e.getMessage());
- return false;
- } finally {
- disconnect(channel);
- }
-
-
- return true;
- }
-
-
- public static Channel openChannel(Session session, String type) throws JSchException {
- if (!session.isConnected()) {
- session.connect(SESSION_TIMEOUT);
- }
- return session.openChannel(type);
- }
-
-
- public static ChannelSftp openSftpChannel(Session session) throws JSchException {
- return (ChannelSftp) openChannel(session, "sftp");
- }
-
-
- public static ChannelExec openExecChannel(Session session) throws JSchException {
- return (ChannelExec) openChannel(session, "exec");
- }
-
-
- /**
- * disconnect
- *
- * @param session
- */
- public static void disconnect(Session session) {
- if (session != null) {
- if (session.isConnected()) {
- try {
- session.disconnect();
- log.info("session disconnect successfully");
- } catch (Exception e) {
- log.error("JSch session disconnect error:", e);
- }
- }
- }
- }
-
-
- /**
- * close connection
- *
- * @param channel channel connection
- */
- public static void disconnect(Channel channel) {
- if (channel != null) {
- if (channel.isConnected()) {
- try {
- channel.disconnect();
- log.info("channel is closed already");
- } catch (Exception e) {
- log.error("JSch channel disconnect error:", e);
- }
- }
- }
- }
-
-
- public static int checkAck(InputStream in) throws IOException {
- int b = in.read();
- // b may be 0 for success,
- // 1 for error,
- // 2 for fatal error,
- // -1
- if (b == 0) {
- return b;
- }
- if (b == -1) {
- return b;
- }
- if (b == 1 || b == 2) {
- StringBuilder sb = new StringBuilder();
- int c;
- do {
- c = in.read();
- sb.append((char) c);
- }
- while (c != '\n');
- if (b == 1) { // error
- log.debug(sb.toString());
- }
- if (b == 2) { // fatal error
- log.debug(sb.toString());
- }
- }
- return b;
- }
-
-
- public static void closeInputStream(InputStream in) {
- if (in != null) {
- try {
- in.close();
- } catch (IOException e) {
- log.error("Close input stream error." + e.getMessage());
- }
- }
- }
-
-
- public static void closeOutputStream(OutputStream out) {
- if (out != null) {
- try {
- out.close();
- } catch (IOException e) {
- log.error("Close output stream error." + e.getMessage());
- }
- }
- }
-
-
- }

- package com.et.jsch;
-
-
- import org.springframework.boot.SpringApplication;
- import org.springframework.boot.autoconfigure.SpringBootApplication;
-
-
- @SpringBootApplication
- public class DemoApplication {
-
-
- public static void main(String[] args) {
- SpringApplication.run(DemoApplication.class, args);
- }
- }
https://github.com/Harries/springboot-demo
- import com.alibaba.fastjson.JSONObject;
- import com.et.jsch.DemoApplication;
- import com.et.jsch.model.Remote;
- import com.et.jsch.util.JSchUtil;
- import com.jcraft.jsch.JSchException;
- import com.jcraft.jsch.Session;
- import org.junit.After;
- import org.junit.Before;
- import org.junit.Test;
- import org.junit.runner.RunWith;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- import org.springframework.boot.test.context.SpringBootTest;
- import org.springframework.test.context.junit4.SpringRunner;
-
-
- import java.io.File;
- import java.io.FileInputStream;
- import java.io.FileNotFoundException;
- import java.io.InputStream;
- import java.util.List;
-
-
-
-
- @RunWith(SpringRunner.class)
- @SpringBootTest(classes = DemoApplication.class)
- public class JSchUtilTests {
- private Logger log = LoggerFactory.getLogger(getClass());
-
-
- Session session;
- @Before
- public void before() throws JSchException {
- Remote remote= new Remote();
- remote.setHost("xxx.xxx.xxx.xxx");
- remote.setUser("root");
- remote.setPassword("xxxx");
- session= JSchUtil.getSession(remote);
- }
- @After
- public void after(){
- JSchUtil.disconnect(session);
- }
- @Test
- public void remoteExecute() throws JSchException {
- List<String> list= JSchUtil.remoteExecute(session,"ls");
- System.out.println(JSONObject.toJSON(list));
- }
- @Test
- public void uploadFile() throws JSchException, FileNotFoundException {
- String filestr ="D:\\tmp\\test\\file_utils\\file1.txt";
- File file = new File(filestr);
- InputStream in = new FileInputStream(file);
-
-
- String directory="/root/test";
- String fileName="test.txt";
- boolean flag= JSchUtil.uploadFile(session,in,directory,fileName);
- System.out.println(flag);
- }
- @Test
- public void deleteFile() throws JSchException, FileNotFoundException {
- String directory="/root/test";
- String fileName="test.txt";
- boolean flag= JSchUtil.deleteFile(session,directory,fileName);
- System.out.println(flag);
- }
- @Test
- public void scpFrom() throws JSchException, FileNotFoundException {
-
-
- String source="/root/test/file1.txt";
- String destination ="D:\\tmp\\scfFrom.txt";
- long filesize= JSchUtil.scpFrom(session,source,destination);
- System.out.println(filesize);
- }
- @Test
- public void scpTo() throws JSchException, FileNotFoundException {
-
-
- String filestr ="D:\\tmp\\test\\file_utils\\file1.txt";
- String destination="/root/test/file1.txt";
- long filesize= JSchUtil.scpTo(session,filestr,destination);
- System.out.println(filesize);
- }
-
-
- }

自己尝试一下吧,非常好的一个工具,更多功能可以去官网看例子
http://www.jcraft.com/jsch/examples/
http://www.liuhaihua.cn/archives/710346.html
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。