在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。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章