我正在编写一个与Linux服务器通信的JUnit集成测试。我正在使用JSch库来执行SSH和SFTP。我注意到使用PuTTY,最初使用SSH连接到服务器需要大约20 - 25秒,但是一旦我进入,shell命令在输入时非常快。但是,当我使用channelExec引用来执行系统命令时,对于每个执行的命令,它需要相同的20 - 25秒。我希望这些命令能够像在PuTTY中输入它们一样快。我注意到程序在从通道读取输入时挂起。在这里执行测试之前初始化JSch会话......
public void connectToServer() {
try {
JSch jsch = new JSch();
session = jsch.getSession(sUserName, sHostName, 22);
session.setPassword(sPassword);
session.setConfig("StrictHostKeyChecking", "no");
if (DEBUG_MODE)
println("UpdateProgram: Establishing SSH Connection...");
session.connect();
if (DEBUG_MODE)
println("UpdateProgram: SSH Connection established.");
if (DEBUG_MODE) println("UpdateProgram: Creating SFTP Channel.");
sftpChannel = (ChannelSftp) session.openChannel("sftp");
sftpChannel.connect();
if (DEBUG_MODE) println("UpdateProgram: SFTP Channel created.");
}
catch (Exception e) {
e.printStackTrace();
System.exit(0);
}
}
会话在所有测试完成后关闭......
public void exit() {
// Close SFTP Channel
if(sftpChannel != null) {
sftpChannel.disconnect();
if (DEBUG_MODE) println("UpdateProgram: SFTP Channel closed.");
}
else {
if (DEBUG_MODE)
println("UpdateProgram: No SFTP Channel to close.");
}
// Close SSH resources
if (session != null) {
session.disconnect();
if (DEBUG_MODE) println("UpdateProgram: SSH Disconnected.");
}
else {
if (DEBUG_MODE)
println("UpdateProgram: No SSH Connection to close.");
}
// Close DB2 database resources
if (conn != null) {
try {
conn.close();
if (DEBUG_MODE) println(
"UpdateProgram: Connection to DB2 database closed.");
}
catch (Exception e) {
e.printStackTrace();
System.exit(0);
}
}
else {
if (DEBUG_MODE)
println("UpdateProgram: No DB2 database connection to close.");
}
}
这是我的测试,它调用处理ChannelExec实例的runCProgram()方法......
public void effDateBeforeYesterday() {
String effDate = null,
testRec = null;
// Set effective date
if(dateSize == 6)
effDate = "000000";
else
effDate = "00000000";
// Upload Base test case and run C program
program.setTransCount(5);
program.put();
program.runCProgram();
// Upload test record
testRec = effDisDateInsert(effDate, currDate, true) + "\n";
IO.fileWrite(testRec, file);
program.setTransCount(1);
program.put();
program.runCProgram();
// Query database for results
// Clear table for next test
assertTrue(true);
}
runCProgram()方法:
public void runCProgram() {
String command = "cd " + updateProgramPath + " && " + "./" + updateProgram
+ " -tc -b. -ppackage -r20150601000000 -n" + transCount + " -d"
+ dbName + " -u" + dbUserName + " -w" + dbPassword + " -s"
+ scheduleName;
ChannelExec channel = null;
InputStream in = null;
try {
// Setup channel for system command execution
channel = (ChannelExec) session.openChannel("exec");
if (DEBUG_MODE) println("UpdateProgram: Exec channel created.");
channel.setCommand(command);
if (DEBUG_MODE)
println("UpdateProgram: Linux Command set to: " + command);
channel.setInputStream(null);
channel.setErrStream(System.err);
in = channel.getInputStream();
channel.connect();
// Used for error detection in C program
int temp = 0;
if (DEBUG_MODE) println("UpdateProgram: Linux output: ");
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()) {
if (in.available() > 0) continue;
temp = channel.getExitStatus();
if (temp != 0) throw new Exception(
"C Program Error, exit status " + temp);
System.out.println("UpdateProgram: exit-status: " + temp);
break;
}
try {
Thread.sleep(1000);
}
catch (Exception ee) {}
}
channel.disconnect();
if (DEBUG_MODE) println("UpdateProgram: Exec channel closed.");
}
似乎为每个命令建立了一个新连接。有没有办法加快ChannelExec参考,以便它可以快速执行系统命令?任何帮助将不胜感激!
答案 0 :(得分:0)
好吧,所以我找到了解决问题的方法。我使用shell通道而不是exec,这样我就可以在程序中随时执行命令。这是我启动shell的代码......
// Global variables
PrintStream shellInput;
PipedInputStream pin2;
private void connectShell() {
PipedInputStream pin = null;
PipedOutputStream pout = null;
PipedOutputStream pout2 = null;
String tmpStr = null;
byte[] tmp = null;
try {
// Setup for channel I/O
pin = new PipedInputStream();
pout = new PipedOutputStream(pin);
pout2 = new PipedOutputStream();
pin2 = new PipedInputStream(pout2);
shellInput = new PrintStream(pout);
// Create channel
shellChannel = session.openChannel("shell");
shellChannel.setInputStream(pin);
shellChannel.setOutputStream(pout2);
if (DEBUG_MODE)
println("UpdateProgram: Connecting to remote shell...");
shellChannel.connect();
// Block until shell is connected
tmpStr = "";
tmp = new byte[1024];
while (!tmpStr.contains("Username String")) {
while (pin2.available() > 0) {
int i = pin2.read(tmp, 0, 1024);
tmpStr = new String(tmp, 0, i);
if (i < 0) break;
print(tmpStr);
}
Thread.sleep(1000);
}
if (DEBUG_MODE)
println("UpdateProgram: Connected to remote shell.");
}
catch (Exception e) {
e.printStackTrace();
System.exit(0);
}
}
我使用shellInput将命令发送到shell,使用pin2读取shell的输出。感谢Martin Prikryl的帮助!