SSH-2實現java連接遠程服務器并執行腳本命令

參考文檔:

    maven jar包:https://mvnrepository.com/artifact/ch.ethz.ganymed/ganymed-ssh2

    Ganymed SSH2 API文檔 :http://www.ganymed.ethz.ch/ssh2/javadoc/overview-summary.html

Java的Ganymed SSH2是一個在純Java中實現SSH-2協議的庫(在J2SE 1.4.2和5.0上測試過)。
它允許從Java程序中連接到SSH服務器。
它支持SSH會話(遠程命令執行和shell訪問)、本地和遠程端口轉發、本地流轉發、X11轉發、SCP和SFTP。

不依賴于任何JCE提供程序,因為所有加密功能都包含在內。

API簡介
一、API中常用的幾個類
Connection:創建服務器連接以及認證(用戶名密碼認證、秘鑰認證等)
Session :會話
SCPClient:可用于文件在不同服務器之間復制。在服務器端,路徑必須存在,如果不存在會報錯。
線程安全的——您可以同時下載(和上傳)不同的文件集,沒有任何問題。
SCPClient實際上是將每個請求映射到不同的會話。

SFTPv3Client: 執條單個指令(推薦使用) 提供了很多方法

二、使用步驟

    1、creates a Connection object.
    2、calls the connect() method.
    3、calls some of the authentication methods (e.g., authenticateWithPublicKey()).

    4、calls one or several times the openSession() method.

三、需要注意

    1、認證成功后,當前目錄就位于/home/username/目錄之下,
        你可以指定腳本文件所在的絕對路徑,或者通過cd導航到腳本文件所在的目錄,
        然后傳遞執行腳本所需要的參數,完成腳本調用執行。
    2、執行腳本以后,可以獲取腳本執行的結果文本,需要對這些文本進行正確編碼后返回給客戶端,避免亂碼產生
    3、如果你需要執行多個linux控制臺腳本,比如第一個腳本的返回結果是第二個腳本的入參,你必須打開多個Session,也就是多次調用Session sess = conn.openSession();,使用完畢記得關閉就可以了

四、代碼

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
 
import org.apache.log4j.Logger;
 
import com.viewhigh.vadp.framework.data.util.StringUtils;
 
import ch.ethz.ssh2.Connection;
import ch.ethz.ssh2.SCPClient;
import ch.ethz.ssh2.Session;
import ch.ethz.ssh2.StreamGobbler;
 
/**
 * 
 * 描述:連接linux服務器并執行相關的shell命令
 * 作者:cuicx
 * 版本:V1.0
 * 創建日期:2018年7月4日 
 * 修改日期: 2018年7月4日
 */
public class ConnectLinuxCommand {
    private static final Logger logger = Logger.getLogger(ConnectLinuxCommand.class);
 
    private static String DEFAULTCHARTSET = "UTF-8";
    private static Connection conn;
    /**
     * 
     * @Title: login  
     * @Description: 用戶名密碼方式  遠程登錄linux服務器
     * @return: Boolean     
     * @throws
     */
    public static Boolean login(RemoteConnect remoteConnect) {
        boolean flag = false;
        try {
            conn = new Connection(remoteConnect.getIp());
            conn.connect();// 連接
            flag = conn.authenticateWithPassword(remoteConnect.getUserName(), remoteConnect.getPassword());// 認證
            if (flag) {
                logger.info("認證成功!");
            } else {
                logger.info("認證失敗!");
                conn.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return flag;
    }
    /**
     * 
    * @Title: loginByKey
    * @Description: 秘鑰方式  遠程登錄linux服務器
    * @param remoteConnect 
    * @param keyFile  一個文件對象指向一個文件,該文件包含OpenSSH密鑰格式的用戶的DSA或RSA私鑰(PEM,不能丟失"-----BEGIN DSA PRIVATE KEY-----" or "-----BEGIN RSA PRIVATE KEY-----"標簽
    * @param keyfilePass 如果秘鑰文件加密 需要用該參數解密,如果沒有加密可以為null
    * @return Boolean
    * @throws
     */
    public static Boolean loginByFileKey(RemoteConnect remoteConnect, File keyFile, String keyfilePass) {
        boolean flag = false;
        // 輸入密鑰所在路徑
        // File keyfile = new File("C:\\temp\\private");
        try {
            conn = new Connection(remoteConnect.getIp());
            conn.connect();
            // 登錄認證
            flag = conn.authenticateWithPublicKey(remoteConnect.getUserName(), keyFile, keyfilePass);
            if (flag) {
                logger.info("認證成功!");
            } else {
                logger.info("認證失敗!");
                conn.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return flag;
    }
    
    /**
     * 
    * @Title: loginByCharsKey
    * @Description: 秘鑰方式  遠程登錄linux服務器
    * @param remoteConnect
    * @param keys  一個字符[],其中包含用戶的DSA或RSA私鑰(OpenSSH密匙格式,您不能丟失“----- begin DSA私鑰-----”或“-----BEGIN RSA PRIVATE KEY-----“標簽。char數組可以包含換行符/換行符。
    * @param keyPass 如果秘鑰字符數組加密  需要用該字段解密  否則不需要可以為null 
    * @return Boolean
    * @throws
     */
    public static Boolean loginByCharsKey(RemoteConnect remoteConnect, char[] keys, String keyPass) {
        boolean flag = false;
        // 輸入密鑰所在路徑
        // File keyfile = new File("C:\\temp\\private");
        try {
            conn = new Connection(remoteConnect.getIp());
            conn.connect();
            // 登錄認證
            flag = conn.authenticateWithPublicKey(remoteConnect.getUserName(), keys, keyPass);
            if (flag) {
                logger.info("認證成功!");
            } else {
                logger.info("認證失敗!");
                conn.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return flag;
    }
    /**
     * 
     * @Title: execute  
     * @Description: 遠程執行shll腳本或者命令
     * @param cmd 腳本命令
     * @return: result 命令執行完畢返回結果     
     * @throws
     */
    public static String execute(String cmd){
        String result = "";
        try {
            Session session = conn.openSession();// 打開一個會話
            session.execCommand(cmd);// 執行命令
            result = processStdout(session.getStdout(), DEFAULTCHARTSET);
            // 如果為得到標準輸出為空,說明腳本執行出錯了
            if (StringUtils.isBlank(result)) {
                result = processStdout(session.getStderr(), DEFAULTCHARTSET);
            }
            conn.close();
            session.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return result;
    }
    /**
    * @Title: executeSuccess
    * @Description: 遠程執行shell腳本或者命令
    * @param shell腳本或者命令
    * @return String 命令執行成功后返回的結果值,如果命令執行失敗,返回空字符串,不是null
    * @throws
     */
    public static String executeSuccess(String cmd){
        String result = "";
        try {
            Session session = conn.openSession();// 打開一個會話
            session.execCommand(cmd);// 執行命令
            result = processStdout(session.getStdout(), DEFAULTCHARTSET);
            conn.close();
            session.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return result;
    }
    /**
     * 
    * @Title: processStdout
    * @Description: 解析腳本執行的返回結果
    * @param in 輸入流對象
    * @param charset 編碼
    * @return String 以純文本的格式返回
    * @throws
     */
    public static String processStdout(InputStream in, String charset){
        InputStream stdout = new StreamGobbler(in);
        StringBuffer buffer = new StringBuffer();
        try {
            BufferedReader br = new BufferedReader(new InputStreamReader(stdout, charset));
            String line = null;
            while ((line = br.readLine()) != null) {
                buffer.append(line + "\n");
            }
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return buffer.toString();
    }
    
    /**
     * 
    * @Title: ConnectLinux
    * @Description: 通過用戶名和密碼關聯linux服務器
    * @return
    * @return String
    * @throws
     */
    public static boolean connectLinux(String ip,String userName,String password,String commandStr) {
        
        logger.info("ConnectLinuxCommand  scpGet===" + "ip:" + ip + "  userName:" + userName + "  commandStr:"
                + commandStr);
        
        String returnStr = "";
        boolean result = true;
        RemoteConnect remoteConnect = new RemoteConnect();
        remoteConnect.setIp(ip);
        remoteConnect.setUserName(userName);
        remoteConnect.setPassword(password);
        try {
            if (login(remoteConnect)) {
                returnStr = execute(commandStr);
                System.out.println(result);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (StringUtils.isBlank(returnStr)) {
            result = false;
        }
        return result;
    }
    /**
     * 
    * @Title: scpGet
    * @Description: 從其他服務器獲取文件到本服務器指定目錄
    * @param host ip(其他服務器)
    * @param username 用戶名(其他服務器)
    * @param password 密碼(其他服務器)
    * @param remoteFile 文件位置(其他服務器)
    * @param localDir 本服務器目錄
    * @throws IOException
    * @return void
    * @throws
     */
    public static void scpGet(String ip, String userName, String password, String remoteFile, String localDir)
            throws IOException {
        
        logger.info("ConnectLinuxCommand  scpGet===" + "ip:" + ip + "  userName:" + userName + "  remoteFile:"
                + remoteFile + "  localDir:" + localDir);
        RemoteConnect remoteConnect = new RemoteConnect();
        remoteConnect.setIp(ip);
        remoteConnect.setUserName(userName);
        remoteConnect.setPassword(password);
        if (login(remoteConnect)) {
            SCPClient client = new SCPClient(conn);
            client.get(remoteFile, localDir);
            conn.close();
        }
    }
    /**
     * 
    * @Title: scpPut
    * @Description: 將文件復制到其他計算機中
    * @param host 
    * @param username
    * @param password
    * @param localFile
    * @param remoteDir
    * @throws IOException
    * @return void
    * @throws
     */
    public static void scpPut(String ip, String userName, String password, String localFile, String remoteDir)
            throws IOException {
        logger.info("ConnectLinuxCommand  scpPut===" + "ip:" + ip + "  userName:" + userName + "  localFile:"
                + localFile + "  remoteDir:" + remoteDir);
        RemoteConnect remoteConnect = new RemoteConnect();
        remoteConnect.setIp(ip);
        remoteConnect.setUserName(userName);
        remoteConnect.setPassword(password);
        if (login(remoteConnect)) {
            SCPClient client = new SCPClient(conn);
            client.put(localFile, remoteDir);
            conn.close();
        }
    }
}
public class RemoteConnect {
    
    private String ip;
    
    private String userName;
    
    private String password;
 
    public String getIp() {
        return ip;
    }
 
    public void setIp(String ip) {
        this.ip = ip;
    }
 
    public String getUserName() {
        return userName;
    }
 
    public void setUserName(String userName) {
        this.userName = userName;
    }
 
    public String getPassword() {
        return password;
    }
 
    public void setPassword(String password) {
        this.password = password;
    }
}
public class CcxTest {
 
       @Test
        public void testDemo() {
           //cd /home/ubuntu/Desktop/music_rec/user_sim/result;cat xyy_result_m10d.json
           //String commandStr="cd /home;rm -rf aa.txt";
           String commandStr="cd /home;cat aa.txt;rm -rf aa.txt";
           Boolean result=ConnectLinuxCommand.connectLinux("192.168.0.11","root","123456",commandStr);
           System.out.println(result);
        }
       @Test
       public void testDemo2() throws IOException {
           try {
               ConnectLinuxCommand.scpGet("192.168.0.11","root","123456", "test.txt", "/home/");
            } catch (Exception e) {
                e.printStackTrace();
            }
       }
       
       @Test
       public void testDemo3() {
           try {
               ConnectLinuxCommand.scpPut("192.168.0.11","root","123456", "test.txt", "/home/");
            } catch (Exception e) {
                e.printStackTrace();
            }
           
           
       }
        
}
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,197評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,415評論 3 415
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,104評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,884評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,647評論 6 408
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,130評論 1 323
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,208評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,366評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,887評論 1 334
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,737評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,939評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,478評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,174評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,586評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,827評論 1 283
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,608評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,914評論 2 372

推薦閱讀更多精彩內容