在工作中,比如我們的產品是需要根據代碼中的情況,時時的去操作遠程的服務器, 所以這樣不能通過固定的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。