標籤:
實際應用中,有時候需要從web管理介面上,遠程去啟動其它linux主機上的程式,利用ssh協議可以方便的滿足這一需求。事實上hadoop架構中,從nn上啟動dn時,就是利用了這一原理。ganymed-ssh2是一個實現了ssh協議的開源項目,項目地址為:http://ganymed-ssh-2.googlecode.com/ (下載源碼要翻強,眾所周知的原因),如果只是使用的話,pom.xml添加以下依賴項就行了:
1 <dependency>2 <groupId>ch.ethz.ganymed</groupId>3 <artifactId>ganymed-ssh2</artifactId>4 <version>262</version>5 </dependency>
為了方便起見,封裝了一個工具類SSHUtil.java:
package com.cnblogs.yjmyzz.utils;import ch.ethz.ssh2.Connection;import ch.ethz.ssh2.Session;import ch.ethz.ssh2.StreamGobbler;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStream;import java.io.InputStreamReader;/** * SSH工具類(可遠程執行其它Linux機器上的Shell命令) * Created by jimmy on 2015/7/6. * http://code.taobao.org/p/y-lib/src/trunk/src/main/java/com/cnblogs/yjmyzz/utils/SSHUtil.java */public class SSHUtil { /** * 串連到主機 * * @param hostname * @param username * @param password * @return * @throws Exception */ private static Connection getConnection(String hostname, String username, String password) throws Exception { Connection conn = null; try { conn = new Connection(hostname); conn.connect(); boolean isAuthenticated = conn.authenticateWithPassword(username, password); if (isAuthenticated == false) { throw new IOException("Authentication failed."); } } catch (Exception e) { throw new IOException("username or password error."); } return conn; } /** * 執行遠程命令 * * @param hostname 遠程主機IP * @param username 使用者名稱 * @param password 密碼 * @param command 需要執行的命令 * @param timeout 逾時時間(秒) * @return * @throws Exception */ public static String execRemoteCommand(String hostname, String username, String password, String command, long timeout) throws Exception { Connection conn = getConnection(hostname, username, password); StringBuilder sb = new StringBuilder(); Session session = null; try { session = conn.openSession(); session.requestPTY("vt100", 80, 24, 640, 480, null); session.execCommand(command); InputStream stdout = new StreamGobbler(session.getStdout()); BufferedReader br = new BufferedReader(new InputStreamReader(stdout)); long start = System.currentTimeMillis(); char[] arr = new char[512]; int read; int i = 0; while (true) { read = br.read(arr, 0, arr.length); if (read < 0 || (System.currentTimeMillis() - start) > timeout * 1000) { break; } sb.append(new String(arr, 0, read)); i++; } } finally { if (session != null) { session.close(); } if (conn != null) { conn.close(); } } return sb.toString(); } /** * 執行遠程命令(預設5秒逾時) * * @param hostname 遠程主機IP * @param username 使用者名稱 * @param password 密碼 * @param command 需要執行的命令 * @return * @throws Exception */ public static String execRemoteCommand(String hostname, String username, String password, String command) throws Exception { return execRemoteCommand(hostname, username, password, command, 5); } /** * 批量執行遠程命令 * * @param hostname 遠程主機IP * @param username 使用者名稱 * @param password 密碼 * @param command 需要執行的命令列表 * @param timeout 逾時時間(秒) * @return * @throws Exception */ public static String execRemoteCommand(String hostname, String username, String password, String[] command, long timeout) throws Exception { Connection conn = getConnection(hostname, username, password); StringBuilder sb = new StringBuilder(); Session session = null; try { for (int t = 0; t < command.length; t++) { session = conn.openSession(); session.requestPTY("vt100", 80, 24, 640, 480, null); session.execCommand(command[t]); InputStream stdout = new StreamGobbler(session.getStdout()); BufferedReader br = new BufferedReader(new InputStreamReader(stdout)); long start = System.currentTimeMillis(); char[] arr = new char[512]; int read; int i = 0; while (true) { read = br.read(arr, 0, arr.length); if (read < 0 || (System.currentTimeMillis() - start) > timeout * 1000) { break; } sb.append(new String(arr, 0, read)); i++; } session.close(); } } finally { if (conn != null) { conn.close(); } } return sb.toString(); } /** * 批量執行遠程命令(預設5秒逾時) * * @param hostname 遠程主機IP * @param username 使用者名稱 * @param password 密碼 * @param command 需要執行的命令列表 * @return * @throws Exception */ public static String execRemoteCommand(String hostname, String username, String password, String[] command) throws Exception { return execRemoteCommand(hostname, username, password, command, 5); }}
使用要點:
1. 如果要連續執行多個命令,用&&串連,比如:先 cd / 切換到根目錄,然後再ls 根目錄下的所有檔案,可以這樣調用:
public static void main(String[] args) { String hostname = "172.21.129.**"; String username = "root"; String password = "***"; try { System.out.println(SSHUtil.execRemoteCommand(hostname, username, password, "pwd&&cd /&&pwd&&ls")); } catch (Exception e) { e.printStackTrace(); } }
上面的命令相當於在同一個session下,連續執行
pwd
cd /
pwd
ls
2. 如果要以後台進程調用命令,傳入命令時,直接加 nohup 即可
利用ganymed-ssh2遠程執行其它Linux機器上的shell命令