1

我写了一个程序,它只是在远程机器上运行一个命令然后停止。有一个程序:

import com.jcraft.jsch.*;
import java.io.*;

public class JSchTest {
    private static String readString(String prompt) {     
        if (prompt != null) {
            System.out.println(prompt);
        }
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));  
        String input = null;
        try {
            input = in.readLine();
        } catch (IOException e) {
            System.err.println(e);
        }        
        return input;
    }

    private static boolean readBoolean(String prompt) {
        while (true) {
            String input = readString(prompt);
            if (input.equalsIgnoreCase("Y") || input.equalsIgnoreCase("N")) {
                return input.equalsIgnoreCase("Y");
            } else {
                System.out.println("Enter Y or N.");
            }
        }
    }

    public static void main(String[] args) throws Exception {  
        JSch jsch = new JSch();
        Session session = jsch.getSession(readString("Login:"),
            readString("Server:"), Integer.parseInt(readString("Port:")));
        session.setUserInfo(
            new UserInfo() {
                @Override
                public String getPassphrase() {
                    return readString("Passphrase:");
                }

                @Override
                public String getPassword() {
                    return readString("Password:");
                }

                @Override
                public boolean promptPassword(String message) {
                    return readBoolean(message);
                }

                @Override
                public boolean promptPassphrase(String message) {
                    return readBoolean(message);
                }

                @Override
                public boolean promptYesNo(String message) {
                    return readBoolean(message);
                }

                @Override
                public void showMessage(String message) {
                    System.out.println(message);
                }
            }
        );
        session.connect();
        ChannelExec channel = (ChannelExec)session.openChannel("exec");
        InputStream in = channel.getInputStream();
        channel.setCommand(readString("Command:"));
        channel.connect();         
        byte[] buffer = new byte[1024]; 
        int bytes;
        do {
            while (in.available() > 0) {
                bytes = in.read(buffer, 0, 1024);
                System.out.print(new String(buffer, 0, bytes));
            }
        } while (!channel.isClosed());                        
        channel.disconnect();
        session.disconnect();            
    }    
}

当我使用仅产生输出的命令时,该程序运行良好,例如echo Hello. 但是当我试图传递一个命令时,比如read VAR;echo You entered: $VAR我的程序运行到无限循环,因为通道没有关闭并且正在等待输入。

好的,所以我得到了channel的输出流来写一个输入

        OutputStream out = channel.getOutputStream();

并使 i/o 循环看起来像这样:

        while (true) {
            while (in.available() > 0) {
                bytes = in.read(buffer, 0, 1024);
                System.out.print(new String(buffer, 0, bytes));
            }
            if (channel.isClosed()) {
                break;
            } else if (true /* channel.isWaitingForInput() */) {
                String output = readString(null) + "\n";
                out.write(output.getBytes());
                out.flush();
            }
        }

但正如你所看到的 - 我没有关于频道另一边发生的事情的信息。是否有我现在必须提供的输入?所以我的程序随时要求输入,即使不需要。

所以有一个问题 - 我怎么知道我什么时候必须为通道传递输入,或者,也许,我怎样才能重写我的程序,这样它不仅会运行命令,而且还为它们提供输入,需要时(但最终还是停止了)?

4

1 回答 1

1

通道保持打开状态,直到断开连接。当您发送退出命令并从主机注销时,它甚至不会自动断开连接。

您需要检查 channel.getExitStatus > -1。退出状态为 -1,直到会话被主机关闭(通常由用户键入“退出”触发)。

一旦退出状态返回不是-1,您可以选择处理退出状态(即,它是一个干净的退出,还是有错误)。之后您需要自行断开频道:

  Channel channel=session.openChannel("shell");

  channel.setInputStream(System.in);
  channel.setOutputStream(System.out);

  channel.connect();

  while (channel.getExitStatus() == -1){
     try{Thread.sleep(1000);}catch(Exception e){System.out.println(e);}
  }

  channel.disconnect();

使用上面的循环,Java 控制台的任何标准输入都将被发送到通道,一旦用户发送“退出”,通道就会断开连接。

这里有一个工作示例:Never ending of reading server response using jSch

此外,jcraft 示例(当您“退出”时实际上并没有关闭,而是一个其他工作示例)。 http://www.jcraft.com/jsch/examples/UserAuthKI.java

于 2013-05-07T17:51:02.190 回答