package com.cattles.schedulingmanagementservice.ssh.jsch;
import com.cattles.schedulingmanagementservice.ssh.*;
import com.jcraft.jsch.*;
import org.apache.log4j.Logger;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
/**
* one instance per connection info,if using tow user connect the same host,please create tow instance
* The JSch is a globe static var,if use key to authenticate ,it must the same to all host
* If the command execute a shell,the script's owner must handle error in script.
* The SSHResult's cmdExitCode is the last command return in the shell unless the shell set it explicitly
* The SSHResult's sysout does't guaranty the message'sequence properly because tow stream handle normal msg and error msg
*
* @author Tom
*/
public class JschCommandExecutor extends BaseCommandExecutor {
private Logger logger = Logger.getLogger(JschCommandExecutor.class);
private Session sshSession;
private volatile static JSch jsch;
private void initJsch() {
synchronized (JschCommandExecutor.class) {
if (jsch == null) {
jsch = new JSch();
}
}
}
private synchronized void initSession(ConnInfo connInfo) throws JSchException {
if (sshSession == null) {
sshSession = jsch.getSession(connInfo.getUser(), connInfo.getHost(), connInfo.getPort());
sshSession.setUserInfo(new JschUserInfo(jsch, connInfo));
}
}
public SSHResult execute(String command) {
SSHResult result = new SSHResult(command);
boolean success = true;
try {
Channel channel = sshSession.openChannel("exec");
((ChannelExec) channel).setCommand(command);
channel.setInputStream(null);
//need to modify
ByteArrayOutputStream errStream = new ByteArrayOutputStream();
((ChannelExec) channel).setErrStream(errStream);
InputStream in = channel.getInputStream();
InputStream errIn = ((ChannelExec) channel).getErrStream();
channel.connect();
// StringBuilder sb = new StringBuilder();
byte[] tmp = new byte[1024];
byte[] errByte = new byte[1024];
while (true) {
while (in.available() > 0) {
int i = in.read(tmp, 0, 1024);
if (i < 0) break;
String msg = new String(tmp, 0, i);
if (!getMonitors().isEmpty()) {
for (SSHMonitor m : getMonitors()) {
m.info(msg);
}
}
logger.info(msg);
result.append(msg);
}
while (errIn.available() > 0) {
int j = errIn.read(errByte, 0, 1024);
if (j < 0) break;
String errMsg = new String(errByte, 0, j);
if (!getMonitors().isEmpty()) {
for (SSHMonitor m : getMonitors()) {
m.info(errMsg);
}
}
logger.error(errMsg);
result.append(errMsg);
success = false;
}
if (channel.isClosed()) {
result.setCmdExitCode(channel.getExitStatus());
break;
}
try {
Thread.sleep(100);
} catch (Exception ee) {
}
}
channel.disconnect();
//Check the command execute successful or not
if (!success || result.getCmdExitCode() != 0) {
result.setSuccess(false);
result.setError(new SSHException("Execute command failed!"));
result.append("Execute command failed!\n");
} else {
result.setSuccess(true);
}
} catch (JSchException e) {
SSHResult.makeFailedResult(result, e, "Execute command failed!\n");
} catch (IOException e) {
SSHResult.makeFailedResult(result, e, "Execute command failed, Io error!\n");
}
return result;
}
public SSHResult connect(ConnInfo info) {
SSHResult result = new SSHResult();
result.setCommand("Connecting to host " + info.getHost());
if (jsch == null) {
initJsch();
}
try {
if (sshSession == null) initSession(info);
// sshSession.setUserInfo(userInfo);
sshSession.connect();
result.setSuccess(true);
result.append("Connect to host " + info.getHost() + " successful!\n");
} catch (JSchException e) {
SSHResult.makeFailedResult(result, e, "Connect to host " + info.getHost() + " failed!\n");
}
return result;
}
public SSHResult disconnect() {
SSHResult result = new SSHResult("Disconnect from host " + sshSession.getHost());
sshSession.disconnect();
result.setSuccess(true);
return result;
}
/* private class JschUserInfo implements UserInfo{
private String password;
private String passphrase;
public JschUserInfo(ConnInfo connInfo) throws JSchException{
switch(connInfo.getAuthType()){
case PASS:
this.password = connInfo.getPassword();
break;
case KEY:
jsch.addIdentity(connInfo.getKeyPath());
this.passphrase = connInfo.getPassphrase();
break;
}
}
public String getPassphrase() {
return this.passphrase;
}
public String getPassword() {
return this.password;
}
public boolean promptPassphrase(String arg0) {
return true;
}
public boolean promptPassword(String arg0) {
return true;
}
public boolean promptYesNo(String arg0) {
return true;
}
public void showMessage(String arg0) {
// TODO Auto-generated method stub
}
}
*/
public SSHResult scp(String origin, String dest, String option) {
if (option == null) option = "";
return JschSCP.SCP(sshSession, origin, dest, option, getMonitors());
}
}