文章出處
文章列表
實際應用中,有時候需要從web管理界面上,遠程去啟動其它linux主機上的程序,利用ssh協議可以方便的滿足這一需求。事實上hadoop架構中,從nn上啟動dn時,就是利用了免密碼ssh登錄。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(已托管在taobao.org上)
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 即可
文章列表
全站熱搜