使用 Jsch 在交互模式下将 java textarea 作为 运行 shell 命令的输入流

Make java textarea as Inputstream to run shell command in interactive mode using Jsch

您好,我正在使用 Jsch 来 运行 我的 shell 命令。我想让它具有交互性。我正在使用 java textarea 来显示 script.This 脚本的输出,也需要一些用户输入。 我怎样才能让这个文本区域接受用户输入和运行命令

public void init(){
try{
  JSch jsch=new JSch();

  Panel panel = new Panel();
  TextArea log = new TextArea();
  panel.add(log);
  add(panel);
  PrintStream printStream = new PrintStream(new CustomOutputStream(log));
  System.setOut(printStream);
  System.setErr(printStream);

  Session session=jsch.getSession("akumar", "banas", 22);
  String passwd = "*****";
  Properties config = new Properties(); 
  config.put("StrictHostKeyChecking", "no");
  session.setConfig(config);
  session.setPassword(passwd);
  session.connect(30000);   // making a connection with timeout.

  Channel channel=session.openChannel("shell");
  channel.setInputStream(System.in);
  channel.setOutputStream(System.out);
  channel.connect(3*1000);

  printStream.println("sftp akumar@banas");

  printStream.flush();

}
catch(Exception e){
  System.out.println(e);
}
  }

// This is the code for making textarea as output stream

 public class CustomOutputStream extends OutputStream {
    private TextArea textArea;

    public CustomOutputStream(TextArea textArea) {
        this.textArea = textArea;
    }

    @Override
    public void write(int b) throws IOException {
        // redirects data to the text area
        textArea.append(String.valueOf((char)b));
        // scrolls the text area to the end of data
        textArea.setCaretPosition(textArea.getText().length());
    }
}

这是一种使用 BlockingQueue 将数据从 JTextField 的 actionListener 传递到 CustomInputStream 的方法。

public class Main extends JFrame {

    public Main() {
        init();
    }

    public void init() {
        try {
            JSch jsch = new JSch();

            JPanel panel = new JPanel();
            panel.setPreferredSize(new Dimension(200, 200));
            JTextArea log = new JTextArea();
            JTextField cmd = new JTextField();
            panel.setLayout(new BorderLayout());
            JScrollPane scrollPane = new JScrollPane(log);
            panel.add(scrollPane, BorderLayout.CENTER);
            panel.add(cmd, BorderLayout.SOUTH);
            add(panel);

            Session session = jsch.getSession("akumar", "banas", 22);
            String passwd = "******";
            Properties config = new Properties();
            config.put("StrictHostKeyChecking", "no");
            session.setConfig(config);
            session.setPassword(passwd);
            session.connect(30000);   // making a connection with timeout.

            Channel channel = session.openChannel("shell");
            channel.setInputStream(new CustomInputStream(cmd));
            channel.setOutputStream(new CustomOutputStream(log));
            channel.connect(3 * 1000);
            pack();

        } catch (Exception e) {
            System.out.println(e);
        }
    }

    public class CustomInputStream extends InputStream implements ActionListener {

        final JTextField field;
        final BlockingQueue<String> q;

        public CustomInputStream(JTextField field) {
            this.field = field;
            q = new LinkedBlockingQueue<>();
            field.addActionListener(this);
        }

        private String s;
        int pos;

        @Override
        public int read() throws IOException {
            while (null == s || s.length() <= pos) {
                try {
                    s = q.take();
                    pos = 0;
                } catch (InterruptedException ex) {
                    Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
            int ret = (int) s.charAt(pos);
            pos++;
            return ret;
        }

        @Override
        public boolean markSupported() {
            return false;
        }

        @Override
        public int read(byte[] b, int off, int len) throws IOException {
            int bytes_copied = 0;
            while (bytes_copied < 1) {
                while (null == s || s.length() <= pos) {
                    try {
                        s = q.take();
                        System.out.println("s = " + s);
                        pos = 0;
                    } catch (InterruptedException ex) {
                        Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
                    }
                }
                int bytes_to_copy = len < s.length()-pos ? len : s.length()-pos;
                System.arraycopy(s.getBytes(), pos, b, off, bytes_to_copy);
                pos += bytes_to_copy;
                bytes_copied += bytes_to_copy;
            }
            return bytes_copied;
        }

        @Override
        public int read(byte[] b) throws IOException {
            return read(b, 0, b.length); //To change body of generated methods, choose Tools | Templates.
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            q.add(field.getText() + "\r\n");
            field.setText("");
        }

    }

// This is the code for making textarea as output stream
    public class CustomOutputStream extends OutputStream {

        private JTextArea textArea;

        public CustomOutputStream(JTextArea textArea) {
            this.textArea = textArea;
        }

        @Override
        public void write(int b) throws IOException {
            // redirects data to the text area
            textArea.append(String.valueOf((char) b));
            // scrolls the text area to the end of data
            textArea.setCaretPosition(textArea.getText().length());
        }

        @Override
        public void write(byte[] b, int off, int len) throws IOException {
            String s = new String(b,off,len);
            textArea.append(s);
            textArea.setCaretPosition(textArea.getText().length());
        }

        @Override
        public void write(byte[] b) throws IOException {
            this.write(b, 0, b.length);
        }
    }

    public static void main(String[] args) {
        java.awt.EventQueue.invokeLater(() -> {
            new Main().setVisible(true);
        });
    }
}