之前做的项目中有一个远程执行脚本的需求,我之前使用的是直接用JSch远程执行命令来echo脚本内容,
果然这几天出现了问题,问题是啥就不赘述了,最后决定使用jsch的sftp方式来进行脚本上传的操作,一开始
遇到各种问题,先是session is down我去网上查了一会资料,发现这篇文章写得不错,有遇到同样问题的可
以看一下CentOS下 配置 sftp,解决问题后又遇到了一个新的问题就是session虽然连接上了,但是在复制文件
的时候总是报2:file is not find,我试着吧目标文件的地址从/root/execshell.sh改成了./execshell之后果然好
了,下面附上我的工具代码:
import com.jcraft.jsch.*;
import java.io.InputStream;
import org.slf4j.LoggerFactory;
import org.slf4j.Logger;
public class JSchSshCLient {
private static final String CLASS_NAME = JSchSshCLient.class.getName();
private static final Logger LOG = LoggerFactory.getLogger(JSchSshCLient.CLASS_NAME);
private static final int DEFAULT_SESSION_TIMEOUT = 30000;
private static final int DEFAULT_CHANNEL_TIMEOUT = 30000;
private static final int DEFAULT_RESPONSE_BUFFER_SIZE = 1024;
private static final String CHANNEL_TYPE = "exec";
private Session session;
public JSchSshCLient(final String ip, final int port, final String username, final String password) throws JSchSshException{
JSchSshCLient.LOG.info("JSchSshCLient initialization: ip(" + ip + "), username(" + username + "), password(" + password + ")");
try {
final JSch jsch = new JSch();
if (JSchSshCLient.LOG.isDebugEnabled()) {
JSchSshCLient.LOG.debug("Trying to establish ssh connection with " + username + "@" + ip + ", password=" + password);
}
(this.session = jsch.getSession(username, ip, port)).setPassword(password);
this.session.setUserInfo(new MyUserInfo() {
@Override
public String getPassword() {
return password;
}
});
this.session.setConfig("StrictHostKeyChecking", "no");
this.session.connect(DEFAULT_SESSION_TIMEOUT);
} catch (Exception e) {
JSchSshCLient.LOG.error("JSchSshCLient init error for ip " + ip + ", message is " + e.getMessage());
throw new JSchSshException("[JSchSshCLient] JSchSshCLient initialization error: init client failed, message:" + e.getMessage());
}
}
public JSchSshCLient(final String ip, final int port, final String username,
final String password,final String filePath) throws JSchSshException{
JSchSshCLient.LOG.info("JSchSshCLient initialization: ip(" + ip + "), username(" + username + "), " +
"filePath("+filePath+").password(" + password + ")");
try {
final JSch jsch = new JSch();
if (JSchSshCLient.LOG.isDebugEnabled()) {
JSchSshCLient.LOG.debug("Trying to establish ssh connection with " + username + "@" + ip
+ ", privatePair="+filePath+"password=" + password);
}
jsch.addIdentity(filePath,password);
this.session=jsch.getSession(username, ip, port);
this.session.setUserInfo(new MyUserInfo() {
@Override
public String getPassword() {
return password;
}
});
this.session.setConfig("StrictHostKeyChecking", "no");
this.session.connect(DEFAULT_SESSION_TIMEOUT);
} catch (Exception e) {
JSchSshCLient.LOG.error("JSchSshCLient init error for ip " + ip + ", message is " + e.getMessage());
throw new JSchSshException("[JSchSshCLient] JSchSshCLient initialization error: init client failed, message:" + e.getMessage());
}
}
public void close() {
this.session.disconnect();
}
public String runCommand(final String command) throws JSchSshException{
Channel channel = null;
try {
channel = this.session.openChannel(CHANNEL_TYPE);
((ChannelExec) channel).setCommand(command);
((ChannelExec) channel).setErrStream(System.err);
final InputStream inStream = channel.getInputStream();
channel.connect(DEFAULT_CHANNEL_TIMEOUT);
final StringBuilder result = new StringBuilder();
final byte[] buffer = new byte[DEFAULT_RESPONSE_BUFFER_SIZE];
while (true) {
if (inStream.available() > 0) {
final int i = inStream.read(buffer, 0, 1024);
if (i >= 0) {
result.append(new String(buffer, 0, i));
continue;
}
}
if (channel.isClosed()) {
break;
}
try {
Thread.sleep(1000L);
} catch (Exception e) {
JSchSshCLient.LOG.error("Sleep error: ", e);
}
}
JSchSshCLient.LOG.info("Command exit status: " + channel.getExitStatus());
inStream.close();
return result.toString();
} catch (Exception e2) {
JSchSshCLient.LOG.error(JSchSshCLient.CLASS_NAME, "runCommand", e2);
throw new JSchSshException(e2);
} finally {
if (channel != null) {
channel.disconnect();
}
}
}
public SshCommandResultVo runCommandWithExitStatus(final String command) {
Channel channel = null;
SshCommandResultVo resultVo = new SshCommandResultVo();
try {
channel = this.session.openChannel(CHANNEL_TYPE);
((ChannelExec) channel).setCommand(command);
((ChannelExec) channel).setErrStream(System.err);
final InputStream inStream = channel.getInputStream();
LOG.info(Thread.currentThread().getName() + " channel.connect...");
channel.connect(DEFAULT_CHANNEL_TIMEOUT);
final StringBuilder result = new StringBuilder();
final byte[] buffer = new byte[DEFAULT_RESPONSE_BUFFER_SIZE];
while (true) {
if (inStream.available() > 0) {
final int i = inStream.read(buffer, 0, 1024);
if (i >= 0) {
result.append(new String(buffer, 0, i));
continue;
}
}
if (channel.isClosed()) {
break;
}
try {
Thread.sleep(1000L);
} catch (Exception e) {
JSchSshCLient.LOG.error("Sleep error: ", e);
}
}
inStream.close();
JSchSshCLient.LOG.info("Command exit status: " + channel.getExitStatus());
resultVo.setExitStatus(channel.getExitStatus());
resultVo.setOutput(result.toString());
} catch (Exception e2) {
JSchSshCLient.LOG.error(Thread.currentThread().getName() + " runCommandWithExitStatus error, " + e2.toString());
resultVo.setException(e2);
} finally {
if (channel != null) {
JSchSshCLient.LOG.info("invoke channel.disconnect...");
channel.disconnect();
}
}
if(null == resultVo.getException()) {
JSchSshCLient.LOG.info("run command success...");
} else {
JSchSshCLient.LOG.info("run command failed...");
}
return resultVo;
}
public void uploadFild(String sourcePath,String targetPath) throws SftpException, JSchException {
ChannelSftp sftpChannel = null;
try {
sftpChannel = (ChannelSftp) session.openChannel("sftp");
sftpChannel.connect();
sftpChannel.put(sourcePath,targetPath);
}
finally {
if(sftpChannel != null){
sftpChannel.disconnect();
}
}
}
public abstract static class MyUserInfo implements UserInfo, UIKeyboardInteractive {
@Override
public abstract String getPassword();
@Override
public boolean promptYesNo(final String str) {
return false;
}
@Override
public String getPassphrase() {
return null;
}
@Override
public boolean promptPassphrase(final String message) {
return false;
}
@Override
public boolean promptPassword(final String message) {
return false;
}
@Override
public void showMessage(final String message) {
}
@Override
public String[] promptKeyboardInteractive(final String destination, final String name, final String instruction, final String[] prompt, final boolean[] echo) {
return null;
}
}
}