更改System.in并以编程方式即时读取System.out(Jsch) [英] Change System.in and read System.out programmly on the fly (Jsch)

查看:330
本文介绍了更改System.in并以编程方式即时读取System.out(Jsch)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在我的代码中,我试图通过SSH在远程服务器上运行一些命令. 这些命令必须相互构建,但后面要有逻辑.这意味着: 当命令a的输出包含"retcode 0"时,则执行命令b.其他命令c

In my code I am trying to run some commands on a remote server via SSH. The commands must build on each other, but with a logic behind it. This means something like: When the output of command a contains "retcode 0", then do command b. Else do command c

我发现无法将这种逻辑实现为几个"exec"命令.似乎每个执行人员"都有自己的流程,因此我无法继续以前的工作.有了一个"exec",我就可以传递所有命令都将被执行的命令列表,因此那里没有逻辑.因此,我决定对Jsch使用"shell". (如果可以使用exec的话,我会很满意的)

I found no way to implement this logic into several "exec" commands. It seems like every "exec" has its own process, so I can’t continue where I was before. And with one "exec" I just can pass a list of commands where all of them will be executed, so no logic there. So, I decided to use "shell" for Jsch. (If there is a way to use exec for it, I would be happy with that)

基于 jcraft 中的示例,我编写了以下代码:

Based on the example from jcraft, I wrote this code:

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.我可以阅读它,决定要使用它做什么,然后输入下一个命令.该命令将在我之前的位置准确执行,所以一切都很好.

Basically, this gives me as a human exact the possibility to do what I want to do. I can enter commands in System.in, the return is printed to System.out. I can read it, decide what I want to do with it and then enter the next command. The command will be executed exact at the point where I was earlier, so everything is fine.

现在,我必须找到一种通过java做到这一点的方法.我找到了一种通过修订字符串输入第一个命令的方法:

Now I have to find a way to do it via java. I found a way to enter the first command through a fix string:

[...]
InputStream testInput = new ByteArrayInputStream( "dir \n".getBytes("UTF-8") );
// Set Streams
channel.setInputStream(testInput);
[...]

但是在那之后,我找不到发送下一个的方法(即使不读取输出,这也是第一步).

But after that I find no way to send the next one (as a first step even without reading the output).

所以,我的问题是,有没有办法通过Java代码设置System.in,它将直接通过Jsch发送此消息(System.setIn()对我不起作用)或另一种更改方式动态输入字符串,以便通过Jsch进行传输?

感谢您的时间!

推荐答案

由于Martin Prikryl的评论,我找到了解决方案. 我用Telnet而不是我的实际应用程序创建了一个小示例.基本原理是相同的,我认为它会更有用,因为当它不是基于特定软件时,更多的人可以尝试并使用它.

Thanks to the comments from Martin Prikryl I found a solution. I created a little example with Telnet instead of my real application. The basics are the same and i think it is more helpfull because more people can try it out and play with it when it is not based on a specific software.

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;
    }
}

这篇关于更改System.in并以编程方式即时读取System.out(Jsch)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆