我尝试使用Jsch执行终端命令。我有3台服务器:1)安装了应用程序的服务器; 2)安装数据库的服务器; 3)我要存储文件的ftp服务器。 我通过使用Jsch api和实用程序“expdp”获得转储并成功转储提取。但后来我想从数据库服务器发送转储到ftp服务器使用Jsch api并命令“lftp -u username ftpServer”和“put dumpFile.dmp”。这不起作用,我不知道为什么。这是我的功能:
public void passDataFromDbServerToFtpServer(String dbUserName, String dbUserPassword, String dbHost, String dbDumpDir,
String ftpUserName, String ftpUserPassword, String ftpDomain, String ftpDir, String fileName) throws ExtractionDumpException {
JSch jsch = new JSch();
Session session = null;
Channel channel = null;
InputStream inputStream = null;
OutputStream outputStream = null;
BufferedReader bufferedReader = null;
String line;
try{
session = jsch.getSession(dbUserName, dbHost, 22);
Properties config = new Properties();
config.put("PreferredAuthentications", "publickey,keyboard-interactive,password");
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
session.setPassword(dbUserPassword);
session.connect();
// String command = "cd " + dbDumpDir + "; pwd; gzip " + fileName + ".dmp; lftp -u " + ftpUserName + " " + ftpDomain;
String command = "lftp -u " + ftpUserName + " " + ftpDomain;
channel = session.openChannel("exec");
((ChannelExec) channel).setCommand(command);
inputStream = channel.getInputStream();
outputStream = channel.getOutputStream();
((ChannelExec) channel).setErrStream(System.err);
bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
channel.connect();
outputStream.write((ftpUserPassword + "\n").getBytes());
// outputStream.write(("pwd; set ssl:verify-certificate no; cd " + ftpDir + "; pwd; put " + fileName + ".dmp.gz; pwd\n").getBytes());
outputStream.write(("pwd\n").getBytes());
outputStream.write(("whoami\n").getBytes());
outputStream.write(("set ssl:verify-certificate no\n").getBytes());
outputStream.write(("cd " + ftpDir + "\n").getBytes());
outputStream.write(("pwd\n").getBytes());
outputStream.write(("put " + fileName + ".dmp.gz\n").getBytes());
outputStream.write(("pwd\n").getBytes());
outputStream.flush();
log.debug("Execute command from dbServer on ftpServer");
while((line = bufferedReader.readLine()) != null){
log.debug(line);
System.out.println(line);
}
} catch (JSchException | IOException e) {
log.error("Dump extraction failed", e);
throw new ExtractionDumpException(e);
} finally {
try {
bufferedReader.close();
inputStream.close();
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
channel.disconnect();
session.disconnect();
}
}
在输出流中我得到: 而且没有别的。 我做错了什么? 我将很感激您的建议。
我使用输出流的原因是在调用命令“lftp -u user ftp”之后我会得到提示,这将提供输入密码。简单的例子:
public static void main(String[] args) {
JSch jsch = null;
Session session = null;
String host = "example";
String user = "example";
String password = "example";
String su_pass = "example";
String su_command = "example";
Channel channel = null;
InputStream in = null;
OutputStream out = null;
BufferedReader bufferedReader = null;
try {
jsch = new JSch();
session = jsch.getSession(user, host, 22);
Properties config = new Properties();
config.put("PreferredAuthentications", "publickey,keyboard-interactive,password");
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
session.setPassword(password);
session.connect();
channel = session.openChannel("exec");
((ChannelExec) channel).setCommand(su_command);
in = channel.getInputStream();
out = channel.getOutputStream();
((ChannelExec)channel).setErrStream(System.err);
channel.connect();
out.write((su_pass+"\n").getBytes());
out.write(("whoami\n").getBytes());
out.write(("pwd\n").getBytes());
out.write(("cd /home/netcrk\n").getBytes());
out.write(("pwd\n").getBytes());
out.write(("mkdir test\n").getBytes());
out.flush();
String line = null;
bufferedReader = new BufferedReader(new InputStreamReader(in));
while((line = bufferedReader.readLine()) != null){
System.out.println(line);
}
// byte[] tmp=new byte[1024];
// while(true){
// while(in.available()>0){
// int i=in.read(tmp, 0, 1024);
// if(i<0)break;
// System.out.print(new String(tmp, 0, i));
// }
// if(channel.isClosed()){
// System.out.println("exit-status: "+channel.getExitStatus());
// break;
// }
// try{Thread.sleep(1000);}catch(Exception ee){}
// }
} catch (JSchException | IOException e) {
e.printStackTrace();
} finally {
try {
in.close();
out.close();
} catch (IOException e) {
e.printStackTrace();
}
channel.disconnect();
session.disconnect();
}
}
可能会在图片上更清楚地解释我尝试做什么。
答案 0 :(得分:0)
如果我没记错的话,ChannelExec
会在您拨打setCommand
时执行channel.connect()
中的任何内容。在您连接后,无法执行多次执行。当然写入输出流不是正确的方法。
您可以设置命令以执行多个操作:
channel.setCommand("pwd; whoami; cd somewhere");
如果那不可能(我还没有测试过),那么我会在你的主机上创建一个脚本,它接受任意数量的参数,然后执行:
channel.setCommand("myScript someDir someFilename");
myScript看起来像:
#!/bin/bash
pwd;
whoami;
set ssl:verify-certificate no;
cd $1;
pwd;
put $2;
pwd;