
如果大家熟悉Linux的話,一定對ssh,sftp,scp等命令非常熟悉,
ssh是一個安全協議,用來在不同系統或者服務器之間進行安全連接,SSH 在連接和傳送的過程中會加密所有的數據。
但是SSH一般是基於客戶端的或者Linux命令行的,比如客戶端的工具:OpenSSH,putty,SSH Tectia;
在linux上大家可以通過ssh username@host連接到所要想連接的主機。
但是如果在J2EE中,如何實現SSH呢?進而可以實現SCP,SFTP的功能呢?下面介紹的JSCH就可以實現下邊的功能。
JSCH是一個純粹的用java實現SSH功能的java library;
maven依賴
<dependency>
<groupId>com.jcraft</groupId>
<artifactId>jsch</artifactId>
<version>0.1.44</version>
</dependency>
關鍵類介紹
- JSch: 作為中心配置點,以及Session的工廠;
- Use getSession to start a new Session.
- Use one of the addIdentity methods for public-key authentication.
- Use setKnownHosts to enable checking of host keys.
- See setConfig for a list of configuration options.
- Session:表示到遠程SSH服務器的一個連接,可以包含多個Channels;
A session is opened with connect() and closed with disconnect().
- Channel : 與Session相關聯的通道,有多種不同類型;
- shell - ChannelShell :A channel connected to a remote shell (本次使用的Channel)
- exec - ChannelExec :A channel connected to a remotely executing program
- direct-tcpip - ChannelDirectTCPIP: A Channel which allows forwarding a pair of local streams to/from a TCP-connection to a server on the remote side
- sftp - ChannelSftp :A Channel connected to an sftp server (as a subsystem of the ssh server).
- subsystem - ChannelSubsystem :A channel connected to a subsystem of the server process
使用步驟
使用Jsch進行SSH連接的具體步驟如下:
- 步驟1: 使用Jsch獲取Session: jsch.getSession()
- 步驟2: 設置Session的password和屬性等: setPassword()/setConfig();
- 步驟3: 設置SocketFactory(可以不進行設置,使用默認的TCP socket);
- 步驟4: 打開Session連接:connect();
- 步驟5: 打開並連接Channel:openChannel()/connect();
- 步驟6: 獲取Channel的inputStream和outputStream,執行指定cmd或其他;
- getInputStream(): All data arriving in SSH_MSG_CHANNEL_DATA messages from the remote side can be read from this stream
- getOutputStream(): All data written to this stream will be sent in SSH_MSG_CHANNEL_DATA messages to the remote side.
- 步驟7: 關閉各種資源:輸入輸出流/Session/Channel等;
創建Session,並打開Session連接
步驟1~步驟4:程序如下


使用SSH協議,連接到Linux,執行指定命令,並獲取結果
步驟5~步驟6:程序如下

執行Shell命令,並獲取執行結果

測試程序



完整程序
JSCHUtil.java
package com.sssppp.Communication;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import java.util.Properties;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.SocketFactory;
/**
* 相關鏈接: JSCH api:http://epaul.github.io/jsch-documentation/javadoc/ Example:
* http://www.jcraft.com/jsch/examples/
*
* @author xxxx
*
*/
public class JSCHUtil {
private static JSch jsch = new JSch();
/**
* 創建Session,並打開Session連接
*
* @param dstIp
* @param dstPort
* @param localIp
* @param localPort
* @param userName
* @param password
* @param timeOut
* @return
* @throws JSchException
*/
public static Session createSession(String dstIp, int dstPort,
final String localIp, final int localPort, String userName,
String password, final int timeOut) throws JSchException {
//jsch.setKnownHosts("/home/foo/.ssh/known_hosts");
// A Session represents a connection to a SSH server
Session session = jsch.getSession(userName, dstIp, dstPort);
session.setPassword(password);
Properties sshConfig = new Properties();
sshConfig.put("StrictHostKeyChecking", "no");//To skip host-key check
session.setConfig(sshConfig);
// this socket factory is used to create a socket to the target host,
// and also create the streams of this socket used by us
session.setSocketFactory(new SocketFactory() {
@Override
public OutputStream getOutputStream(Socket socket)
throws IOException {
return socket.getOutputStream();
}
@Override
public InputStream getInputStream(Socket socket) throws IOException {
return socket.getInputStream();
}
@Override
public Socket createSocket(String host, int port)
throws IOException, UnknownHostException {
Socket socket = new Socket();
if (localIp != null) {
socket.bind(new InetSocketAddress(InetAddress
.getByName(localIp), localPort));
}
socket.connect(
new InetSocketAddress(InetAddress.getByName(host), port),
timeOut);
return socket;
}
});
session.connect(timeOut);
return session;
}
}
SSHCommUtil.java
package com.sssppp.Communication;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import com.jcraft.jsch.Channel;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
public class SSHCommUtil {
/**
* 測試程序
* @param args
*/
public static void main(String[] args) {
String ip = "10.180.137.241";
int port = 22;
String localIp = null;
int localPort = 0;
int timeOut = 3000;
String userName = "xxx";
String password = "xxx";
String[] cmds = new String[] { "ifconfig | grep eth0\n",
"cat /etc/redhat-release\n" };
String[] result = null;
try {
result = execShellCmdBySSH(ip, port, localIp, localPort, timeOut,
userName, password, cmds);
} catch (Exception e) {
e.printStackTrace();
}
if (result != null) {
for (String string : result) {
System.out.println(string);
System.out.println("-------------------");
}
}
}
/**
* 使用SSH協議,連接到Linux Shell,執行腳本命令,並獲取結果
*
* @param dstIp
* @param dstport
* default :22
* @param localIp
* @param localPort
* @param timeOut
* @param userName
* @param password
* @param cmds
* @return
* @throws Exception
*/
public static String[] execShellCmdBySSH(String dstIp, int dstport,
String localIp, int localPort, int timeOut, String userName,
String password, String... cmds) throws Exception {
Session session = null;
Channel channel = null;
InputStream is = null;
OutputStream os = null;
try {
session = JSCHUtil.createSession(dstIp, dstport, localIp,
localPort, userName, password, timeOut);
channel = session.openChannel("shell");
// Enable agent-forwarding.
// ((ChannelShell)channel).setAgentForwarding(true);
// Choose the pty-type "vt102".
// ((ChannelShell)channel).setPtyType("vt102");
// Set environment variable "LANG" as "ja_JP.eucJP".
// ((ChannelShell)channel).setEnv("LANG", "ja_JP.eucJP");
channel.connect();
is = channel.getInputStream();
os = channel.getOutputStream();
String[] result = new String[cmds.length];
for (int i = 0; i < cmds.length; i++) {
result[i] = sendCommand(is, os, cmds[i]);
}
return result;
} catch (JSchException e) {
if (e.getMessage().contains("Auth fail")) {
throw new Exception("Auth error");
} else {
throw new Exception("Connect error");
}
} catch (Exception e) {
throw e;
} finally {
try {
is.close();
} catch (IOException e) {
}
try {
os.close();
} catch (IOException e) {
}
channel.disconnect();
session.disconnect();
}
}
/**
* 執行Shell命令,並獲取執行結果
*
* @param is
* @param os
* @param cmd
* @return
* @throws IOException
*/
private static String sendCommand(InputStream is, OutputStream os,
String cmd) throws IOException {
os.write(cmd.getBytes());
os.flush();
StringBuffer sb = new StringBuffer();
int beat = 0;
while (true) {
if (beat > 3) {
break;
}
if (is.available() > 0) {
byte[] b = new byte[is.available()];
is.read(b);
sb.append(new String(b));
beat = 0;
} else {
if (sb.length() > 0) {
beat++;
}
try {
Thread.sleep(sb.toString().trim().length() == 0 ? 1000
: 300);
} catch (InterruptedException e) {
}
}
}
return sb.toString();
}
}