在java中打开shell并与其I/O交互

在java中打开shell并与其I/O交互,java,linux,process,terminal,processbuilder,Java,Linux,Process,Terminal,Processbuilder,我试图打开一个shell(xterm)并与之交互(编写命令并读取shell的输出) 下面是一个不起作用的代码示例: public static void main(String[] args) throws IOException { Process pr = new ProcessBuilder("xterm").start(); PrintWriter pw = new PrintWriter(pr.getOutputStream()); pw.println("ls

我试图打开一个shell(xterm)并与之交互(编写命令并读取shell的输出)

下面是一个不起作用的代码示例:

public static void main(String[] args) throws IOException {
    Process pr = new ProcessBuilder("xterm").start();
    PrintWriter pw = new PrintWriter(pr.getOutputStream());
    pw.println("ls");
    pw.flush();
    InputStreamReader in = new InputStreamReader(pr.getInputStream());
    System.out.println(in.read());
}
当我执行此程序时,会打开一个“xterm”窗口,并且不会输入“ls”命令。 只有当我关闭窗口时,才会打印“-1”,并且从外壳上看不到任何内容

重要-

我知道我可以用:
Process pr=新的ProcessBuilder(“ls”).start()

获取输出,但我需要打开“xterm”用于其他用途


非常感谢

您的问题是xterm进程的标准输入和输出与终端窗口中可见的实际shell不对应。直接运行shell进程可能比使用xterm更成功:

Process pr = new ProcessBuilder("sh").start();
一个完整的java主示例,介绍如何在
Java8
上与
shell
交互(在Java4、5、6上进行交互非常简单)

输出示例

$ javac Main.java
$ java Main
echo "hi"
hi
代码

import java.io.*;
import java.util.Arrays;
import java.util.List;
import java.util.Scanner;


public class Main {

    public static void main(String[] args) throws IOException, InterruptedException {

        final List<String> commands = Arrays.asList("/bin/sh");
        final Process p = new ProcessBuilder(commands).start();

        // imprime erros
        new Thread(() -> {
            BufferedReader ir = new BufferedReader(new InputStreamReader(p.getErrorStream()));
            String line = null;
            try {
                while((line = ir.readLine()) != null){
                    System.out.printf(line);
                }
            } catch(IOException e) {}
        }).start();

        // imprime saida
        new Thread(() -> {
            BufferedReader ir = new BufferedReader(new InputStreamReader(p.getInputStream()));
            String line = null;
            try {
                while((line = ir.readLine()) != null){
                    System.out.printf("%s\n", line);
                }
            } catch(IOException e) {}
        }).start();

        // imprime saida
        new Thread(() -> {
            int exitCode = 0;
            try {
                exitCode = p.waitFor();
            } catch(InterruptedException e) {
                e.printStackTrace();
            }
            System.out.printf("Exited with code %d\n", exitCode);
        }).start();


        final Scanner sc = new Scanner(System.in);
        final BufferedWriter bf = new BufferedWriter(new OutputStreamWriter(p.getOutputStream()));
        final String newLine = System.getProperty("line.separator");
        while(true){
            String c = sc.nextLine();
            bf.write(c);
            bf.newLine();
            bf.flush();
        }

    }

}
import java.io.*;
导入java.util.array;
导入java.util.List;
导入java.util.Scanner;
公共班机{
公共静态void main(字符串[]args)引发IOException、InterruptedException{
最终列表命令=Arrays.asList(“/bin/sh”);
final Process p=新的ProcessBuilder(commands).start();
//临时错误
新线程(()->{
BufferedReader ir=新的BufferedReader(新的InputStreamReader(p.getErrorStream());
字符串行=null;
试一试{
而((line=ir.readLine())!=null){
系统输出打印F(行);
}
}捕获(IOE){}
}).start();
//即兴赛达
新线程(()->{
BufferedReader ir=新的BufferedReader(新的InputStreamReader(p.getInputStream());
字符串行=null;
试一试{
而((line=ir.readLine())!=null){
System.out.printf(“%s\n”,第行);
}
}捕获(IOE){}
}).start();
//即兴赛达
新线程(()->{
int-exitCode=0;
试一试{
exitCode=p.waitFor();
}捕捉(中断异常e){
e、 printStackTrace();
}
System.out.printf(“已退出,代码为%d\n”,退出代码);
}).start();
最终扫描仪sc=新扫描仪(System.in);
final BufferedWriter bf=new BufferedWriter(new OutputStreamWriter(p.getOutputStream());
最后一个字符串newLine=System.getProperty(“line.separator”);
while(true){
字符串c=sc.nextLine();
bf.写入(c);
bf.newLine();
bf.flush();
}
}
}

标题有误导性。xterm是运行shell的终端应用程序。它本身不是一个贝壳。我知道这已经有好几年了,但其他人会看到的。这个解决方案本身不起作用。对于您想要的工作,您需要添加-i以使其具有交互性。在我意识到我应该检查一下文档中的/bin/sh之前,我已经用了一个小时的时间在脑袋上敲了敲