【问题标题】:Getting output from executing a terminal command in a java code running inside Cubieboard Platform在 Cubieboard Platform 内运行的 java 代码中执行终端命令获取输出
【发布时间】:2014-01-27 22:36:25
【问题描述】:

我用于在 Linux Debian 中运行终端命令并在 java 程序中获取输出的代码是这样的:

public static String execute(String command) {
    StringBuilder sb = new StringBuilder();
    String[] commands = new String[]{"/bin/sh", "-c", command};
    try {
        Process proc = new ProcessBuilder(commands).start();
        BufferedReader stdInput = new BufferedReader(new
                InputStreamReader(proc.getInputStream()));

        BufferedReader stdError = new BufferedReader(new
                InputStreamReader(proc.getErrorStream()));

        String s = null;
        while ((s = stdInput.readLine()) != null) {
            sb.append(s);
            sb.append("\n");
        }

        while ((s = stdError.readLine()) != null) {
            sb.append(s);
            sb.append("\n");
        }
    } catch (IOException e) {
        return e.getMessage();
    }
    return sb.toString();
}

现在的问题是,它适用于像ls / 这样的普通命令,并返回适当的结果。但我的目标是运行如下命令:

echo 23 > /sys/class/gpio/export

例如,用于激活 CubieBoard 平台中的 gpio 引脚。 (Cubieboard 是类似于 Raspberry Pi 的迷你 PC 板)。

现在在系统本身的终端中运行此命令,可以正常工作并给我正确的结果。但是当我从这个java代码运行它时,我无法得到任何结果。

关键是,它可以工作并且命令执行得很好,但是我无法获得命令的输出消息!

例如,如果 pin 在过去是活动的,那么通常它应该给我返回如下结果:

bash: echo: write error: Device or resource busy

但是当我通过上面的 java 代码运行这个命令时,我没有得到任何响应。 (再次生效但只是我无法得到终端的响应!)

当我运行代码时,代码中的stdInputstdError 变量都具有null 的值。 :(

请帮助我完成我的项目。这是唯一剩下的部分:(

谢谢。

【问题讨论】:

    标签: java linux terminal gpio


    【解决方案1】:

    可能childProcess没有运行到结束

    请尝试:

    proc.waitFor()

    并在 proc.waitFor() 之前在其他线程中运行 read stdInput 和 stdError。

    示例:

    public static String execute(String command) {
            String[] commands = new String[] { "/bin/sh", "-c", command };
    
            ExecutorService executor = Executors.newCachedThreadPool();
            try {
                ProcessBuilder builder = new ProcessBuilder(commands);
    
                /*-
                Process proc = builder.start();
                CollectOutput collectStdOut = new CollectOutput(
                        proc.getInputStream());
                executor.execute(collectStdOut);
    
                CollectOutput collectStdErr = new CollectOutput(
                        proc.getErrorStream());
                executor.execute(collectStdErr);
                // */
    
                // /*-
                // merges standard error and standard output
                builder.redirectErrorStream();
                Process proc = builder.start();
                CollectOutput out = new CollectOutput(proc.getInputStream());
                executor.execute(out);
                // */
                // child proc exit code
                int waitFor = proc.waitFor();
    
                return out.get();
            } catch (IOException e) {
                return e.getMessage();
            } catch (InterruptedException e) {
                // proc maybe interrupted
                e.printStackTrace();
            }
            return null;
        }
    
        public static class CollectOutput implements Runnable {
            private final StringBuffer buffer = new StringBuffer();
            private final InputStream inputStream;
    
            public CollectOutput(InputStream inputStream) {
                super();
                this.inputStream = inputStream;
            }
    
            /*
             * (non-Javadoc)
             * 
             * @see java.lang.Runnable#run()
             */
            @Override
            public void run() {
                BufferedReader reader = null;
                String line;
                try {
                    reader = new BufferedReader(new InputStreamReader(inputStream));
                    while ((line = reader.readLine()) != null) {
                        buffer.append(line).append('\n');
                    }
                } catch (Exception e) {
                    System.err.println(e);
                } finally {
                    try {
                        reader.close();
                    } catch (IOException e) {
                    }
                }
    
            }
    
            public String get() {
                return buffer.toString();
            }
        }
    

    【讨论】:

    • 哦,谢谢,但是你能给我一个示例代码吗?这样会更清楚吗??
    • 我实现了它,但仍然无法正常工作。该过程需要很长时间才能完成,例如 30 秒。但同样没有返回结果。它仍然适用于“ls /”等普通命令。此外,当我观察从 waitFor() 命令返回的变量时,它的值是 1。
    【解决方案2】:

    代码是对的,就在第二行,我改了

    "/bin/sh" to "/bin/bash"
    

    一切正常!

    sh == bash?

    长期以来,/bin/sh 在大多数 GNU/Linux 系统上都指向 /bin/bash。因此,忽略两者之间的差异几乎是安全的。但这种情况最近开始发生变化。

    /bin/sh 不指向 /bin/bash 的一些流行的系统示例(其中一些 /bin/bash 甚至可能不存在)是:

    1. 现代 Debian 和 Ubuntu 系统,默认将 sh 符号链接为 dash;

    2. Busybox,通常在 Linux 系统启动期间作为 initramfs 的一部分运行。它使用 ash shell 实现。

    3. BSD。 OpenBSD 使用 korn shell 的后代 pdksh。 FreeBSD 的 sh 是原始 UNIX Bourne shell 的后代。

    有关这方面的更多信息,请参阅: Difference between sh and bash

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-03-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-12-15
      • 1970-01-01
      • 2013-02-01
      • 2020-02-19
      相关资源
      最近更新 更多