当前位置: 首页 > 知识库问答 >
问题:

如何以字符串形式获取JSCHshell命令输出

谭嘉容
2023-03-14

我使用JSCH-SSH库在“shell”通道中执行命令,但无法找到一种方法来做两件事:-

1)如何查找命令是否在远程unix box上完全执行?

2)如何在String中捕获命令输出,而不是在System.out控制台上打印?

下面是我的代码片段,它可以很好地在系统上显示shell命令输出。出来

注意:我不想使用“exec”通道,因为它为每个命令启动一个新进程,并且不记得导出的“session”变量。我必须使用“shell”频道。

下面是我的代码片段。感谢您的帮助。谢谢你抽出时间。

try{

  String commandToRun = "ls /tmp/*.log \n";
  if(channel.isClosed())
      channel=session.openChannel("shell");
  byte[] bytes = commandToRun.getBytes();
  ByteArrayInputStream bais=new ByteArrayInputStream(bytes);
  channel.setInputStream(bais);
  InputStream ins=channel.getInputStream();
  channel.connect();
  channel.setOutputStream(System.out);//This prints on console. Need 2 capture in String somehow?

  //in-efficient way to allow command to execute completely on remote Unix machine
  //DO NOT know a better way, to know when command is executed completely
  Thread.sleep(5000L);
}
 catch(Exception e){
  System.out.println("Exception  in executeCommand() --->"+ e.getMessage());
  e.printStackTrace();
}

共有3个答案

江曦
2023-03-14

以Mihail提供的例子、互联网上的其他信息和马丁的反馈为例,这里有一个使用exec重新设计的解决方案。请注意,打开会话允许发送多个命令,每个命令都打开自己的输入/输出通道。

Rant:我真的不喜欢让进程的输出流写入。多么烦人的范例(至少对我来说)。我想要的是将我的输出写入的流程输入流,但我很难确定它是反向的。仅仅是我还是下面的(伪代码)没有更合理的解释??

频道。getInputStream()。写(“这里有一些文字要写进我的频道。”)

String ret=频道。getOutputStream()。getOutput()

无论如何,感谢Mihail和Martin的评论/意见。

public class SSHConnectionManager {

    private Session session;

    private String username = "user";
    private String password = "password";
    private String hostname = "myhost";

    public SSHConnectionManager() { }

    public SSHConnectionManager(String hostname, String username, String password) {
        this.hostname = hostname;
        this.username = username;
        this.password = password;
    }

    public void open() throws JSchException {
        open(this.hostname, this.username, this.password);
    }

    public void open(String hostname, String username, String password) throws JSchException{

        JSch jSch = new JSch();

        session = jSch.getSession(username, hostname, 22);
        Properties config = new Properties(); 
        config.put("StrictHostKeyChecking", "no");  // not recommended
        session.setConfig(config);
        session.setPassword(password);

        System.out.println("Connecting SSH to " + hostname + " - Please wait for few seconds... ");
        session.connect();
        System.out.println("Connected!");
    }

    public String runCommand(String command) throws JSchException, IOException {

        String ret = "";

        if (!session.isConnected())
            throw new RuntimeException("Not connected to an open session.  Call open() first!");

        ChannelExec channel = null;
        channel = (ChannelExec) session.openChannel("exec");

        channel.setCommand(command);
        channel.setInputStream(null);

        PrintStream out = new PrintStream(channel.getOutputStream());
        InputStream in = channel.getInputStream(); // channel.getInputStream();

        channel.connect();

        // you can also send input to your running process like so:
        // String someInputToProcess = "something";
        // out.println(someInputToProcess);
        // out.flush();

        ret = getChannelOutput(channel, in);

        channel.disconnect();

        System.out.println("Finished sending commands!");

        return ret;
    }


    private String getChannelOutput(Channel channel, InputStream in) throws IOException{

        byte[] buffer = new byte[1024];
        StringBuilder strBuilder = new StringBuilder();

        String line = "";
        while (true){
            while (in.available() > 0) {
                int i = in.read(buffer, 0, 1024);
                if (i < 0) {
                    break;
                }
                strBuilder.append(new String(buffer, 0, i));
                System.out.println(line);
            }

            if(line.contains("logout")){
                break;
            }

            if (channel.isClosed()){
                break;
            }
            try {
                Thread.sleep(1000);
            } catch (Exception ee){}
        }

        return strBuilder.toString();   
    }

    public void close(){        
        session.disconnect();
        System.out.println("Disconnected channel and session");
    }


    public static void main(String[] args){

        SSHConnectionManager ssh = new SSHConnectionManager();
        try {
            ssh.open();
            String ret = ssh.runCommand("ls -l");

            System.out.println(ret);
            ssh.close();

        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

米夕
2023-03-14

对于2)您可以使用ByteArrayOutputStream

final ByteArrayOutputStream baos = new ByteArrayOutputStream();
channel.setOutputStream(baos);

然后从新字符串(baos.toByteArray())创建新字符串

对于1,您是否尝试使用2

String commandToRun = "ls /tmp/*.log 2>&1 \n";

阎晔
2023-03-14

OP可能不再需要我的解决方案,但是任何正在寻找解决方案来满足这两个条件的人1)等待远程机器上的命令完成;和2)将输出捕获为字符串;你可以尝试这样做:

public class SshConnectionManager {

private static Session session;
private static ChannelShell channel;
private static String username = "";
private static String password = "";
private static String hostname = "";


private static Session getSession(){
    if(session == null || !session.isConnected()){
        session = connect(hostname,username,password);
    }
    return session;
}

private static Channel getChannel(){
    if(channel == null || !channel.isConnected()){
        try{
            channel = (ChannelShell)getSession().openChannel("shell");
            channel.connect();

        }catch(Exception e){
            System.out.println("Error while opening channel: "+ e);
        }
    }
    return channel;
}

private static Session connect(String hostname, String username, String password){

    JSch jSch = new JSch();

    try {

        session = jSch.getSession(username, hostname, 22);
        Properties config = new Properties(); 
        config.put("StrictHostKeyChecking", "no");
        session.setConfig(config);
        session.setPassword(password);

        System.out.println("Connecting SSH to " + hostname + " - Please wait for few seconds... ");
        session.connect();
        System.out.println("Connected!");
    }catch(Exception e){
        System.out.println("An error occurred while connecting to "+hostname+": "+e);
    }

    return session;

}

private static void executeCommands(List<String> commands){

    try{
        Channel channel=getChannel();

        System.out.println("Sending commands...");
        sendCommands(channel, commands);

        readChannelOutput(channel);
        System.out.println("Finished sending commands!");

    }catch(Exception e){
        System.out.println("An error ocurred during executeCommands: "+e);
    }
}

private static void sendCommands(Channel channel, List<String> commands){

    try{
        PrintStream out = new PrintStream(channel.getOutputStream());

        out.println("#!/bin/bash");
        for(String command : commands){
            out.println(command);
        }
        out.println("exit");

        out.flush();
    }catch(Exception e){
        System.out.println("Error while sending commands: "+ e);
    }

}

private static void readChannelOutput(Channel channel){

    byte[] buffer = new byte[1024];

    try{
        InputStream in = channel.getInputStream();
        String line = "";
        while (true){
            while (in.available() > 0) {
                int i = in.read(buffer, 0, 1024);
                if (i < 0) {
                    break;
                }
                line = new String(buffer, 0, i);
                System.out.println(line);
            }

            if(line.contains("logout")){
                break;
            }

            if (channel.isClosed()){
                break;
            }
            try {
                Thread.sleep(1000);
            } catch (Exception ee){}
        }
    }catch(Exception e){
        System.out.println("Error while reading channel output: "+ e);
    }

}

public static void close(){
    channel.disconnect();
    session.disconnect();
    System.out.println("Disconnected channel and session");
}


public static void main(String[] args){
    List<String> commands = new ArrayList<String>();
    commands.add("ls -l");

    executeCommands(commands);
    close();
}
}

如果您需要一次发送多个命令并保持通道打开以便以后重用,此解决方案也很有用。

 类似资料:
  • 问题内容: 在python中,我可以使用os或subprocess运行一些系统命令。问题是我无法以字符串形式获取输出。例如: 我有一个没有功能check_out的较旧版本的子流程,并且我希望有一个不需要更新该模块的解决方案,因为我的代码将在没有完全管理员权限的服务器上运行。 这个问题似乎微不足道,但我找不到微不足道的解决方案 问题答案: 用途: 执行此操作的较新方法(> python 2.6)是使

  • 问题内容: 我正在使用JSCH -SSH库在“ shell”通道中执行命令,但找不到找到两种方法的方法: 1)如何查找命令是否在远程unix box上完全执行? 2)如何在String中捕获命令输出,而不是在System.out控制台上打印它? 下面是我的代码片段,可以在system.out上显示shell命令输出 注意:我不想使用“ exec”通道,因为它为每个命令启动一个新进程,并且不记得已导

  • 在Dart中提供枚举之前,我编写了一些繁琐且难以维护的代码来模拟枚举,现在我想简化它。我需要以字符串形式获取枚举的名称,例如可以用Java完成,但不能。 例如,小测试代码片段返回'day。星期一“在每种情况下,我想要的是”星期一” 我是否正确,要获得“星期一”,我需要解析字符串?

  • 问题内容: xml看起来像这样: 我正在使用stax一次处理一个“ ”,并且可以正常工作。我需要以字符串的形式获取整个语句节点,以便创建“ 123.xml”和“ 456.xml”,甚至可以将其加载到按帐户索引的数据库表中。 使用这种方法:http : //www.devx.com/Java/Article/30298/1954 我正在寻找做这样的事情: 问题答案: 为什么不只使用xpath? 您可

  • 问题内容: 说我有这个PHP代码: 然后,我需要一个这样的功能: 打印: 任何想法如何实现这一目标?在PHP中甚至有可能吗? 问题答案: 您可以使用get_defined_vars()来查找与您要查找其名称的变量具有相同值的变量的名称。显然,这并不总是可行的,因为不同的变量通常具有相同的值,但这是我想到的唯一方法。 编辑:get_defined_vars()似乎不能正常工作,它返回’var’,因为