当前位置: 首页 > 面试题库 >

JSch问题-无法检索完整的命令输出

麻宾白
2023-03-14
问题内容

我正在使用JSch连接到SSH并执行命令。其中一个命令给出了很大的输出。在终端中,如果执行命令,则必须按Enter键才能查看整个输出。使用JSch,我无法检索整个输出。

当我使用交互式终端登录时,命令输出在填充屏幕后停止并等待Enter

该代码取自 如何在String中获取jschshell命令输出:

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

问题答案:

通常,您不应使用“ shell”通道来自动执行命令。

“外壳”通道旨在实现交互式外壳会话。

因此,它要求PTY(伪终端),它具有对人类友好但对机器不友好的副作用,会破坏代码。

请改用“ exec”通道。

请参阅在Java中使用JSchexec从ArrayList执行命令列表

如果您出于某种原因需要或想要使用“ shell”频道(但无论如何,它都会咬住您),请确保在致电.setPty(false)之前致电.connect

channel = (ChannelShell)getSession().openChannel("shell");
channel.setPty(false);
channel.connect();

旁注:

  • "#!/bin/bash"是一个纯粹的无稽之谈。Shell会忽略所有以#(开头的命令)开头的命令。没有意义发送它。
  • 不要使用StrictHostKeyChecking=no


 类似资料:
  • < b >想改进这个问题?通过编辑此帖子添加详细信息并澄清问题。 我正在使用JSch连接到SSH并执行命令。其中一个命令给出了一个很大的输出。在终端中,如果您执行命令,则必须按回车键才能看到整个输出。使用 JSch 我无法检索整个输出。 当我使用交互式终端登录时,命令输出在填充屏幕后停止,并等待Enter。 代码取自如何在String中获取jsch shell命令输出:

  • 问题内容: 我有以下代码: 试图从阅读器中读取内容已挂起。我该如何解决?我该如何寻找正在发生的事情? 问题答案: 在等待命令完成的同时,必须连续读取输出。否则,如果命令产生足够的输出以填充输出缓冲区,则该命令将挂起,等待缓冲区被消耗,这将永远不会发生。这样您就陷入僵局。 以下示例在监视命令状态的同时连续读取stdout和stderr。它基于官方的JSch 示例 (仅添加了stderr的阅读)。 如

  • 谁能帮我修一下吗?我正在尝试在colab中安装pyenchant,以便在单词拼写错误时执行可能的建议。我想使用。这就是我所尝试的; 但它输出以下错误; 我的想法是得到一些可能的建议,如果一个词是错的,我计划做以下几点 有人能建议我如何做到这一点吗?我正在研究colab。请帮助我如何在colab中安装,或者在单词错误时我可以获得任何其他可能的建议。

  • 我们如何在docker history命令输出的第三列(由创建)中看到完整命令? 第三列(CREATED BY)是命令的缩写,这使得重建原始Dockerfile变得困难。是否可以在第三列中获得完整的命令? 感谢阅读。

  • 我正在尝试获取Spotify API访问令牌。根据Spotify API站点的这些说明: 请求将包括请求正文中的参数: null null 生成: 我正试图在这样的球拍中实现这一点: http.rkt 这很奇怪,因为它告诉我,即使我的grant_type是client_credentials(请参见当我调用on)时,我的grant_type不受支持。是什么导致了这一切?

  • 我是Jsch的新手,我正在尝试通过SFTP连接到第三方。我可以通过ssh连接,因此我知道我有正确的用户、主机、端口和私钥文件,但当我尝试通过Jsch连接时,我得到异常消息“auth failed”,这几乎是有用的,但不是很有用。下面是我从网上的例子中拼凑出来的代码: 我添加了一些日志,这样我就知道失败是以session.connect()的形式发生的。我捕获了用户和connectionURL并验证