Java 动态更改System.in和读取System.out(Jsch)
在我的代码中,我试图通过SSH在远程服务器上运行一些命令。 这些命令必须相互建立,但背后有一个逻辑。这意味着: 当命令a的输出包含“retcode 0”时,则执行命令b。否则,请执行命令c 我发现没有办法将这种逻辑实现到几个“exec”命令中。似乎每个“执行官”都有自己的流程,所以我不能继续我以前的工作。使用一个“exec”,我可以传递一个命令列表,所有命令都将在其中执行,因此没有逻辑。所以,我决定对Jsch使用“shell”。 (如果有办法使用exec,我会很高兴的) 基于中的示例,我编写了以下代码:Java 动态更改System.in和读取System.out(Jsch),java,ssh,inputstream,jsch,Java,Ssh,Inputstream,Jsch,在我的代码中,我试图通过SSH在远程服务器上运行一些命令。 这些命令必须相互建立,但背后有一个逻辑。这意味着: 当命令a的输出包含“retcode 0”时,则执行命令b。否则,请执行命令c 我发现没有办法将这种逻辑实现到几个“exec”命令中。似乎每个“执行官”都有自己的流程,所以我不能继续我以前的工作。使用一个“exec”,我可以传递一个命令列表,所有命令都将在其中执行,因此没有逻辑。所以,我决定对Jsch使用“shell”。 (如果有办法使用exec,我会很高兴的) 基于中的示例,我编写了以
import com.jcraft.jsch.*;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
public class Main {
public static void main(String[] args) {
try {
JSch jsch = new JSch();
String user = "sshuser";
String host = "localhost";
Session session = jsch.getSession(user, host, 22);
String passwd = "password";
session.setPassword(passwd);
session.setConfig("StrictHostKeyChecking", "no");
//session.connect();
session.connect(30000); // making a connection with timeout.
Channel channel = session.openChannel("shell");
// Enable agent-forwarding.
((ChannelShell)channel).setAgentForwarding(true);
// Set Streams
channel.setInputStream(System.in);
channel.setOutputStream(System.out);
channel.connect(3 * 1000);
} catch (Exception e) {
System.out.println(e);
}
}
}
基本上,这给了我作为一个人做我想做的事情的可能性。我可以在System.in中输入命令,返回值将打印到System.out。我可以阅读它,决定我想用它做什么,然后输入下一个命令。命令将在我之前执行的位置执行,因此一切正常
现在我必须找到一种通过java实现的方法。我找到了通过修复字符串输入第一个命令的方法:
[...]
InputStream testInput = new ByteArrayInputStream( "dir \n".getBytes("UTF-8") );
// Set Streams
channel.setInputStream(testInput);
[...]
但是在那之后,我没有办法发送下一个(作为第一步,即使不读取输出)
那么,我的问题是,有没有一种方法可以通过Java代码设置System.in,该代码将通过Jsch直接发送(System.setIn()对我不起作用),或者通过另一种方法动态更改输入字符串,以便通过Jsch传输?
谢谢你的时间 多亏了Martin Prikryl的评论,我找到了一个解决方案。 我用Telnet创建了一个小示例,而不是我的实际应用程序。基本原理是一样的,我认为它更有用,因为当它不基于特定的软件时,更多的人可以尝试并使用它
import com.jcraft.jsch.*;
import java.io.*;
public class Main {
public static void main(String[] args) {
OutputStream out = null;
Session session = null;
try {
JSch jsch = new JSch();
String user = "sshuser";
String host = "localhost";
session = jsch.getSession(user, host, 22);
String passwd = "password";
session.setPassword(passwd);
session.setConfig("StrictHostKeyChecking", "no");
// vars and objects used later
String lineSeperator = System.getProperty("line.separator");
StringBuilder sb = new StringBuilder();
Main main = new Main();
//session.connect();
session.connect(30000); // making a connection with timeout.
ChannelExec channel = (ChannelExec) session.openChannel("exec");
InputStream in = channel.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
// start telnet session
channel.setCommand("telnet 192.168.222.128 -l sshuser");
out = channel.getOutputStream();
channel.connect();
// wait a little bit for telnet to be ready to take the input
Thread.sleep(500);
// pass the password
out.write(("password\n").getBytes());
out.write(("\n").getBytes());
Thread.sleep(500);
// flush reader, very important!
out.flush();
// Read from Bufferreader until the current line contains a specific string
// For my real application it would be "--- END", for this example i
// used something from the last line my machine returns. Very important that this string
// appears on every possible output, or you will stuck in a while loop!
//
// Tried it with while((reader.readline())!=null) but this ends in a infinity loop too.
// Since in my application there is an String that always get returned i didn't look it further up
String responeFromLogin = main.readOutput("security updates.", reader, lineSeperator, sb);
// Working with the response, in this example a simple fail-->Exception, success --> progress
if (responeFromLogin.contains("Login incorrect")) {
throw new Exception("Failed: Login");
}
System.out.println("Login Successfull");
// Log in was successful, so lets do the next command, basiclly the same routine again
out.write(("dir\n").getBytes());
Thread.sleep(500);
out.flush();
// Again, not bulletproofed in this example
String responseFromHelp = main.readOutput("examples.desktop", reader, lineSeperator, sb);
if (!responseFromHelp.contains("test")) {
throw new Exception("Failed: Help");
}
System.out.println("Folder Found");
} catch (InterruptedException e1) {
e1.printStackTrace();
} catch (IOException e1) {
e1.printStackTrace();
} catch (JSchException e1) {
e1.printStackTrace();
} catch (Exception e1) {
e1.printStackTrace();
} finally {
try {
if (out != null) {
out.flush();
}
} catch (IOException e1) {
e1.printStackTrace();
}
System.out.println("_________________________");
System.out.println("I am done");
if (session != null) {
session.disconnect();
}
}
}
public String readOutput(String endString, BufferedReader reader, String lineSeperator, StringBuilder sb) {
String line;
String returnString = "Error";
while (true) {
try {
line = reader.readLine();
if (line.contains(endString)) {
sb.append(line).append(lineSeperator);
returnString = sb.toString();
break;
} else {
sb.append(line).append(lineSeperator);
}
} catch (IOException e) {
returnString = "Error";
e.printStackTrace();
}
}
return returnString;
}
}
多亏了Martin Prikryl的评论,我找到了一个解决方案。 我用Telnet创建了一个小示例,而不是我的实际应用程序。基本原理是一样的,我认为它更有用,因为当它不基于特定的软件时,更多的人可以尝试并使用它
import com.jcraft.jsch.*;
import java.io.*;
public class Main {
public static void main(String[] args) {
OutputStream out = null;
Session session = null;
try {
JSch jsch = new JSch();
String user = "sshuser";
String host = "localhost";
session = jsch.getSession(user, host, 22);
String passwd = "password";
session.setPassword(passwd);
session.setConfig("StrictHostKeyChecking", "no");
// vars and objects used later
String lineSeperator = System.getProperty("line.separator");
StringBuilder sb = new StringBuilder();
Main main = new Main();
//session.connect();
session.connect(30000); // making a connection with timeout.
ChannelExec channel = (ChannelExec) session.openChannel("exec");
InputStream in = channel.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
// start telnet session
channel.setCommand("telnet 192.168.222.128 -l sshuser");
out = channel.getOutputStream();
channel.connect();
// wait a little bit for telnet to be ready to take the input
Thread.sleep(500);
// pass the password
out.write(("password\n").getBytes());
out.write(("\n").getBytes());
Thread.sleep(500);
// flush reader, very important!
out.flush();
// Read from Bufferreader until the current line contains a specific string
// For my real application it would be "--- END", for this example i
// used something from the last line my machine returns. Very important that this string
// appears on every possible output, or you will stuck in a while loop!
//
// Tried it with while((reader.readline())!=null) but this ends in a infinity loop too.
// Since in my application there is an String that always get returned i didn't look it further up
String responeFromLogin = main.readOutput("security updates.", reader, lineSeperator, sb);
// Working with the response, in this example a simple fail-->Exception, success --> progress
if (responeFromLogin.contains("Login incorrect")) {
throw new Exception("Failed: Login");
}
System.out.println("Login Successfull");
// Log in was successful, so lets do the next command, basiclly the same routine again
out.write(("dir\n").getBytes());
Thread.sleep(500);
out.flush();
// Again, not bulletproofed in this example
String responseFromHelp = main.readOutput("examples.desktop", reader, lineSeperator, sb);
if (!responseFromHelp.contains("test")) {
throw new Exception("Failed: Help");
}
System.out.println("Folder Found");
} catch (InterruptedException e1) {
e1.printStackTrace();
} catch (IOException e1) {
e1.printStackTrace();
} catch (JSchException e1) {
e1.printStackTrace();
} catch (Exception e1) {
e1.printStackTrace();
} finally {
try {
if (out != null) {
out.flush();
}
} catch (IOException e1) {
e1.printStackTrace();
}
System.out.println("_________________________");
System.out.println("I am done");
if (session != null) {
session.disconnect();
}
}
}
public String readOutput(String endString, BufferedReader reader, String lineSeperator, StringBuilder sb) {
String line;
String returnString = "Error";
while (true) {
try {
line = reader.readLine();
if (line.contains(endString)) {
sb.append(line).append(lineSeperator);
returnString = sb.toString();
break;
} else {
sb.append(line).append(lineSeperator);
}
} catch (IOException e) {
returnString = "Error";
e.printStackTrace();
}
}
return returnString;
}
}
是否确实需要在同一个shell中运行这些命令(您错误地称之为“进程”)?请解释一下原因。你可能错了。通过命令,我将更改应用程序中的上下文。因此,第一个命令将让我登录,第二个命令将为该命令设置特定区域,然后第三个命令是实际命令。据我所知,使用新的shell时,我将始终从同一个起点开始,因此在这种情况下不会登录。如果有办法在最后一个shell结束的地方继续,我可以使用新的shell。好的,那么这些不是“命令”(关于SSH=shell命令),而是一些应用程序的输入行或者,如果您的“设备”实际上不是普通的[Linux]机器,而是某种特殊的机器,那么这些命令就是某些应用程序的输入行。在这个应用程序中,可以使用“exec”传递一个任务的所有命令,但随后所有命令都会被匆忙输入。因此,如果第一次登录成功,则无需验证。应用程序总是在输出的末尾返回一个“END”,因此在Stream中很容易对此进行解析。您的问题在“exec”和“shell”通道中措辞混乱。实际上,您只执行一个顶级[shell]命令(应用程序)。因此,如果您使用“shell”或“exec”通道,从您的问题的角度来看,这实际上并不重要,因为只有一个顶级命令。所以使用“exec”通道可以避免“shell”通道出现问题。子命令(应用程序命令)需要作为输入传递给应用程序。为此,请参阅。是否确实需要在同一个shell中运行这些命令(您错误地称之为“进程”)?请解释一下原因。你可能错了。通过命令,我将更改应用程序中的上下文。因此,第一个命令将让我登录,第二个命令将为该命令设置特定区域,然后第三个命令是实际命令。据我所知,使用新的shell时,我将始终从同一个起点开始,因此在这种情况下不会登录。如果有办法在最后一个shell结束的地方继续,我可以使用新的shell。好的,那么这些不是“命令”(关于SSH=shell命令),而是一些应用程序的输入行或者,如果您的“设备”实际上不是普通的[Linux]机器,而是某种特殊的机器,那么这些命令就是某些应用程序的输入行。在这个应用程序中,可以使用“exec”传递一个任务的所有命令,但随后所有命令都会被匆忙输入。因此,如果第一次登录成功,则无需验证。应用程序总是在输出的末尾返回一个“END”,因此在Stream中很容易对此进行解析。您的问题在“exec”和“shell”通道中措辞混乱。实际上,您只执行一个顶级[shell]命令(应用程序)。因此,如果您使用“shell”或“exec”通道,从您的问题的角度来看,这实际上并不重要,因为只有一个顶级命令。所以使用“exec”通道可以避免“shell”通道出现问题。子命令(应用程序命令)需要作为输入传递给应用程序。为此,请参见。