在java中通过shell命令远程操作服务器(SSH)

在工作中,比如我们的产品是需要根据代码中的情况,时时的去操作远程的服务器, 所以这样不能通过固定的shell脚本去完成,所以就只能在java中通过shell命令远程的操作服务器。所以本博客就是,在java中,通过使用shell命令操作远程的服务器。 本类包含: 远程执行shell命令, 文件上传下载,文件删除,查询文件列表几个方法。 话不多说,直接上代码:

准备工作:

因为这个是使用的jsch工具,所以需要首先导入这个包, maven下引入:

	<dependency>
	    <groupId>com.jcraft</groupId>
	    <artifactId>jsch</artifactId>
	    <version>0.1.55</version>
	</dependency>

非maven项目的话,可以通点击后面下载jar包:点击下载
,没有积分的可以后面留言,我发送到邮箱

1. 为了方便管理,我先把登陆需要输入的ip,帐号,密码使用一个实体类来进行封装,代码如下:

package com.bdm.pojo;

import java.io.Serializable;

/**
 *@Packge: com.bdm.pojo
 *@Description: 远程连接服务器并发送命令的登陆信息
 *@author: mulming
 *@data: Dec 25, 2019 10:54:04 AM
 */
public class SSHLoginInfo  implements Serializable{
	/**
	 *@Packge: com.bdm.pojo
	 *@author: mulming
	 *@data: Dec 25, 2019 11:16:30 AM
	 */
	private static final long serialVersionUID = 1L;
	private String ipAddress;// ip 地址
	private String userName;// 登陆帐号
	private String passWord;// 登陆密码
	
	public String getIpAddress() {
		return ipAddress;
	}

	public String getUserName() {
		return userName;
	}

	public String getPassWord() {
		return passWord;
	}

	public static class Builder{
		private String ipAddress;// ip 地址
		private String userName;// 登陆帐号
		private String passWord;// 登陆密码
		
		public Builder setIpAddress(String ipAddress) {
			this.ipAddress = ipAddress;
			return this;
		}
		public Builder setUserName(String userName) {
			this.userName = userName;
			return this;
		}
		public Builder setPassWord(String passWord) {
			this.passWord = passWord;
			return this;
		}
		
		public SSHLoginInfo build() {
			return new SSHLoginInfo(this);
		}
	}

	private SSHLoginInfo(Builder builder) {
		this.ipAddress = builder.ipAddress;
		this.userName = builder.userName;
		this.passWord = builder.passWord;
	}
}

2. 管理连接的工具类,以及封装的常用方法,代码如下:

package com.bdm.ssh.util;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Properties;
import java.util.Vector;
import org.apache.log4j.Logger;
import com.bdm.common.tools.DBCommonTools;
import com.bdm.pojo.SSHLoginInfo;
import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelExec;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.ChannelSftp.LsEntry;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.SftpException;

/**
 *@Packge: com.shell
 *@Description: exec用于执行命令;sftp用于文件处理
 *@author: mulming
 *@data: Dec 23, 2019 9:03:41 PM
 */
public class SSHRemoteUtil {

	public static Logger LOG = Logger.getLogger(SSHRemoteUtil.class);
	private static volatile SSHRemoteUtil instance = null;
	private static final int DEFAULT_PORT = 22;// 默认端口号
	private Session session;// JSCH session
	
	private boolean logined = false;// 是否登陆
	
	private SSHRemoteUtil() {}
	
	public static SSHRemoteUtil getInstance() {
		if(instance == null) {
			synchronized (DBCommonTools.class) {
				if(instance == null) {
					instance = new SSHRemoteUtil(); 
				}
			}
		}
		return instance;
	}

	/**
	 *@Description: 远程登陆
	 *@author: mulming
	 *@param: @param ipAddress ip
	 *@param: @param userName 帐号
	 *@param: @param password 密码
	 *@param: @throws Exception
	 *@return: void
	 */
    public void sshRemoteCallLogin(SSHLoginInfo loginInfo) {
        // 如果登陆就直接返回
        if (logined) {
            return;
        }
        // 创建jSch对象
        JSch jSch = new JSch();
        try {
            // 获取到jSch的session, 根据用户名、主机ip、端口号获取一个Session对象
            session = jSch.getSession(loginInfo.getUserName(), loginInfo.getIpAddress(), DEFAULT_PORT);
            // 设置密码
            session.setPassword(loginInfo.getPassWord());

            Properties config = new Properties();
            config.put("StrictHostKeyChecking", "no");
            session.setConfig(config);
            // session.setTimeout(3000);// 设置超时
            session.connect(); 通过Session建立连接

            // 设置登陆状态
            logined = true;
            LOG.info("SSH connection success ...");
        } catch (JSchException e) {
            // 设置登陆状态为false
            logined = false;
            LOG.info("主机登录失败, IP = " + loginInfo.getIpAddress() + ", USERNAME = " + loginInfo.getUserName() + ", Exception:" + e);
        }
    }

    /**
     * 关闭连接
     */
    public void closeSession() {
        // 调用session的关闭连接的方法
        if (session != null) {
            // 如果session不为空,调用session的关闭连接的方法
            session.disconnect();
        }
        LOG.info("SSH close success ...");
    }

    /**
     *@Description: 执行相关的命令
     *@author: mulming
     *@param: @param command 具体的命令
     *@param: @throws IOException
     *@return: String : 返回命令执行后的结果
     */
    public String execCommand(String command){
        InputStream in = null;// 输入流(读)
        Channel channel = null;// 定义channel变量
        try {
            // 如果命令command不等于null
            if (command != null) {
                // 打开channel
                //说明:exec用于执行命令;sftp用于文件处理
                channel = session.openChannel("exec");
                // 设置command
                ((ChannelExec) channel).setCommand(command);
                // channel进行连接
                channel.connect();
                // 获取到输入流
                in = channel.getInputStream();
                // 执行相关的命令
                String processDataStream = processDataStream(in);
                return processDataStream;
            }
        } catch (JSchException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if (in != null) {
                try {
					in.close();
				} catch (IOException e) {
					LOG.error(e);
					e.printStackTrace();
				}
            }
            if (channel != null) {
                channel.disconnect();
            }
        }
        return null;
    }

    /**
     *@Description:内部使用 对将要执行的linux的命令进行遍历,专门处理执行,以及执行后返回的命令
     *@author: mulming
     *@param: @param in
     *@param: @return
     *@param: @throws Exception
     *@return: String
     */
    private String processDataStream(InputStream in){
        StringBuffer sb = new StringBuffer();
        BufferedReader br = new BufferedReader(new InputStreamReader(in));
        String result = "";
        try {
            while ((result = br.readLine()) != null) {
                sb.append(result + "\n");
            }
        } catch (Exception e) {
        	LOG.error("Failed to get BufferedReader: ",e);
        } finally {
        	if(br != null) {
        		try {
        			br.close();
        		} catch (IOException e) {
        			LOG.error(e);
        		}
        	}
        }
        return sb.toString();
    }

    /**
     *@Description: 上传文件 可参考:https://www.cnblogs.com/longyg/archive/2012/06/25/2556576.html
     *@author: mulming
     *@param: @param directory 上传文件的目录,即服务端的目录
     *@param: @param uploadFile 将要上传的文件,本地文件
     *@return: void
     */
    public void uploadFile(String directory, String uploadFile) {
        try {
        	System.out.println(" Upload start .....");
            // 打开channelSftp
            ChannelSftp channelSftp = (ChannelSftp) session.openChannel("sftp");
            // 远程连接
            channelSftp.connect();
            // 创建一个文件名称问uploadFile的文件
            File file = new File(uploadFile);
            // 将文件进行上传(sftp协议)
            // 将本地文件名为src的文件上传到目标服务器,目标文件名为dst,若dst为目录,则目标文件名将与src文件名相同.
            // 采用默认的传输模式:OVERWRITE
            channelSftp.put(new FileInputStream(file), directory, ChannelSftp.OVERWRITE);
            // 切断远程连接
            channelSftp.exit();
            System.out.println( file.getName() + " Upload success .....");
        } catch (JSchException e) {
            e.printStackTrace();
        } catch (SftpException e) {
            e.printStackTrace();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }

    /**
     *@Description: TODO下载文件 采用默认的传输模式:OVERWRITE
     *@author: mulming
     *@param: @param src linux服务器文件地址
     *@param: @param dst 本地存放地址
     *@return: void
     */
    public void fileDownload(String src, String dst){
        try {
			// src 是linux服务器文件地址,dst 本地存放地址
			ChannelSftp channelSftp = (ChannelSftp) session.openChannel("sftp");
			// 远程连接
			channelSftp.connect();
			// 下载文件,多个重载方法
			channelSftp.get(src, dst);
			// 切断远程连接,quit()等同于exit(),底层 disconnect();
			channelSftp.quit(); 
		} catch (JSchException e) {
			LOG.error(e);
			e.printStackTrace();
		} catch (SftpException e) {
			LOG.error(e);
			e.printStackTrace();
		}
        LOG.info(src + " ,download complete.....");
    }

    /**
     *@Description: 删除文件
     *@author: mulming
     *@param: @param directoryFile 要删除文件所在目录
     *@return: void
     */
    public void deleteFile(String directoryFile) throws SftpException, JSchException {
        // 打开openChannel的sftp
        ChannelSftp channelSftp = (ChannelSftp) session.openChannel("sftp");
        // 远程连接
        channelSftp.connect();
        // 删除文件
        channelSftp.rm(directoryFile);
        // 切断远程连接
        channelSftp.exit();
        LOG.info(directoryFile + " delete complete.....");
    }

    /**
     *@Description: 列出目录下的文件
     *@author: mulming
     *@param: @param directory   要列出的目录
     *@param: @throws JSchException
     *@param: @throws SftpException
     *@return: Vector<LsEntry>
     */
    public Vector<LsEntry> listFiles(String directory) throws JSchException, SftpException {
        ChannelSftp channelSftp = (ChannelSftp) session.openChannel("sftp");
        // 远程连接
        channelSftp.connect();
        // 显示目录信息
        @SuppressWarnings("unchecked")
		Vector<LsEntry> ls = channelSftp.ls(directory);
        // 切断连接
        channelSftp.exit();
        return ls;
    }
}

3. 建立测试类,测试工具,代码如下:

package com.shell;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Vector;

import org.junit.After;
import org.junit.Test;

import com.jcraft.jsch.ChannelSftp.LsEntry;
import com.bdm.pojo.SSHLoginInfo;
import com.bdm.ssh.util.SSHRemoteUtil;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.SftpException;

public class TestOracleEXP {
	
	static {
		 //int port;// 端口号
	    String ipAddress = "xxx";// ip地址 
	    String userName = "xxx";// 账号
	    String password = "xxx";// 密码
		try {
//			首先远程连接ssh
			SSHLoginInfo info=new SSHLoginInfo.Builder().setIpAddress(ipAddress).setUserName(userName).setPassWord(password).build();
			SSHRemoteUtil.getInstance().sshRemoteCallLogin(info);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	@After // 7、关闭连接
	public void CloseConn() {
		System.out.println("close conn ...");
        SSHRemoteUtil.getInstance().closeSession();
	}
	
	@Test //测试执行命令
	public void TestExecCommand() throws IOException {
		 String command = "ls /opt ";
         String string = SSHRemoteUtil.getInstance().execCommand(command);
         System.out.println(string);
	}
	
	@Test // 测试上传文件
	public void TestUploadFile() {
		 String directory = "/home/bdm/mlm1.text";// 目标文件名
         String uploadFile = "/home/marico/mlm.test";// 本地文件名
         SSHRemoteUtil.getInstance().uploadFile(directory, uploadFile);
	}

	@Test //测试下载文件
	public void TestFileDownLoad() throws JSchException, SftpException {
		String src = "/home/bdm/mlm1.text";
        String dst = "/home/marico";
        SSHRemoteUtil.getInstance().fileDownload(src, dst);
	}
	
	@Test
	public void TestDeleteFile() throws SftpException, JSchException {
		SSHRemoteUtil.getInstance().deleteFile("/home/bdm/mlm.txt");
	}
	
	@Test
	public void TestListFiles() throws JSchException, SftpException {
		Vector<LsEntry> listFiles = SSHRemoteUtil.getInstance().listFiles("/home/bdm");
		for(LsEntry s:listFiles) {
			//System.out.println(s.getLongname());
//			System.out.println(s.getFilename());
			System.out.println(s.getClass());
		}
	}
}

4. 测试的部分结果:

读取文件夹下文件数量:
在这里插入图片描述删除文件:
在这里插入图片描述下载文件:
在这里插入图片描述其他的就不一一列举啦, 如果觉得还好用,麻烦顶一下 3KS。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值