JSch shell返回StringArray

时间:2014-04-07 00:45:37

标签: java jsch

我试图在不接触它的10年后重新学习Java。我想从我想要编写的其他一些应用程序中使用JSch创建一个库。我有连接,但我现在正在使用stdin和stdout。 我希望有一个方法接受String中的单个命令,并返回带有结果的ArrayList。

任何帮助都会很棒!

//This vars are in the class.
private JSch _jsch;
private Session _session;
private Channel _channel;

这是我的连接方法

public boolean Connect () throws JSchException
{
    try {
        _jsch = new JSch();
        _session = _jsch.getSession(_user, _hostname, _port);      
        _session.setPassword(_password);
        _session.setConfig("StrictHostKeyChecking", "no");  

        _channel = _session.openChannel("shell");

        //((ChannelShell)_channel).setPtyType("vt100");

        _channel.setInputStream(bais);
        _channel.setOutputStream(baos);
        _channel.connect(3000);                     
    }//try to connect
    catch (JSchException ex)
    {
        throw ex;
    }
    return true;
}

目标是,一旦我打开连接,我就可以向该方法发送命令并将结果返回到数组中。根据结果​​执行并发送更多命令。我不想每次都关闭连接,因为它们将构建在它之前的命令上。我不知道如何使用输入和输出流足以获得我正在寻找的结果。如果您能协助填写以下方法,我将不胜感激。

public List<String> ExecuteCommand (String command) {
    //run command to existing connection
    //Get returned lines to Array List and return the list
}

谢谢

3 个答案:

答案 0 :(得分:0)

这是一个运行本地流程并创建一个返回ArrayList的示例,该流程与流程的输出一行一行地填充。虽然它不是你想要的,但它应该给你一个想法。

public List<String> ExecuteCommand (String command) {
    Runtime r = Runtime.getRuntime();
    Process p = r.exec(command);
    p.waitFor();
    BufferedReader b = new BufferedReader(new InputStreamReader(p.getInputStream()));
    String line = "";
    ArrayList<String> output = new ArrayList<String>();
    while ((line = b.readLine()) != null) {
        output.add(line);
    }
    return output;
}

答案 1 :(得分:0)

我创建了open source project (click to see)来实现远程文件系统。这是最重要的代码段,它也支持sudo。在该示例中,我将错误输出重定向到标准输出。 如果您不想输出错误,可以将其删除。在示例中,我使用StringWriter而不是List&lt; String&gt;。我鼓励你使用它。

/**
 * Executes commands at target host.
 * @throws IOException Failed to capture a return code
 */
public int exec(boolean sudo, String command, StringWriter output) throws IOException {
    ChannelExec channel = null;
    try {
        channel = (ChannelExec) session.openChannel("exec");
        sudo = sudo && !username.equals("root");
        if (sudo) {
            command = "sudo -S -p '' " + command;
            channel.setPty(true);
        }
        channel.setCommand(command);

        InputStream stdout = channel.getInputStream(); // The stream will be recycled automatically
        InputStream stderr = channel.getErrStream(); // The stream will be recycled automatically
        channel.connect();

        boolean passwordEntered = false;
        if (sudo && !StringUtils.isEmpty(password)) {
            OutputStream stdin = channel.getOutputStream();
            stdin.write(password.getBytes());
            stdin.write("\n".getBytes());
            IOUtils.closeQuietly(stdin);
            passwordEntered = true;
        }

        String contents = readFully(stdout);
        if (passwordEntered) {
            contents = contents.substring(password.length());
        }
        output.write(contents.trim());
        contents = readFully(stderr);

        int retval = channel.getExitStatus();
        if (retval != 0) {
            output.append(contents.trim());
        }
        return retval;
    }
    catch (JSchException ex) {
        throw new IOException(ex);
    }
    finally {
        output.flush();
        if (channel != null) {
            channel.disconnect();
        }
    }
}

private static String readFully(InputStream input) throws IOException {
    StringBuilder output = new StringBuilder();
    int bytesRead = input.read();
    while (bytesRead != -1) {
        output.append((char) bytesRead);
        bytesRead = input.read();
    }
    return output.toString();
}

答案 2 :(得分:0)

这是我目前的解决方案。它可以使用一些流衬里和清理,但它正在让我得到我想要的东西。

我并不想将此标记为答案,但我还没有发布到此网站,如果我做错了,请原谅我。这是新的连接方法

public boolean Connect () throws JSchException
{
    try {
        _jsch = new JSch();
        _session = _jsch.getSession(_user, _hostname, _port);      
        _session.setPassword(_password);
        _session.setConfig("StrictHostKeyChecking", "no");  

        _session.connect();
        _channel = _session.openChannel("shell");

        _channel.setInputStream(null);

        _isInput = _channel.getInputStream();
        _isOutput = _channel.getOutputStream();

        _reader = new BufferedReader (new InputStreamReader(_isInput));
        _writer = new BufferedWriter (new OutputStreamWriter (_isOutput));

        _channel.connect(3000);   

        LastLogin = _reader.readLine(); //get last login message
    }//try to connect
    catch (JSchException ex)
    {
        throw ex;
    }
    catch (UnsupportedEncodingException uee)
    {
        return false;
    }
    catch (IOException ioe)
    {
        return false;
    }
    return true;
}

这是我的执行方法。我知道有更好的方法可以从char []到ArrayList,但我还没有解决这个问题。

public List<String> ExecuteCommand (String command)
{

    List<String> returns = new ArrayList();
    try {
        _writer.write(command);


        if ( !command.endsWith("\n") )
            _writer.write("\n");

        _writer.flush();
        Thread.sleep(2000); //allow time to exec

        int c;
        StringBuilder response= new StringBuilder();

        while (_reader.ready()) {
            c = _reader.read();
            if (c == -1)
                break;
            response.append( (char)c ) ;  
        }//while

        String[] lines = response.toString().split("\n");
        for (String line: lines)
        {
            if (line.trim().length()!=0)
                returns.add(line);
        }

    }//try
    catch (IOException e)
    {
        //handle this later
    }//catch
    catch (InterruptedException ie)
    {
        //handle this later
    }
    return returns;
}//ExecuteCommand

我知道它不是很好但是有效。