【问题标题】:How to execute a interactive shell script using java Runtime?如何使用 java Runtime 执行交互式 shell 脚本?
【发布时间】:2012-03-29 14:29:32
【问题描述】:

我想知道有没有办法执行下面的 shell 脚本,它使用 java 的 Runtime 类等待用户输入?

#!/bin/bash

echo "Please enter your name:"
read name
echo "Welcome $name"

我正在使用以下 java 代码来执行此任务,但它只显示空白控制台。

public class TestShellScript {
public static void main(String[] args) {

        File wd = new File("/mnt/client/");
           System.out.println("Working Directory: " +wd);
           Process proc = null;

           try {
               proc = Runtime.getRuntime().exec("sudo ./test.sh", null, wd);

           } catch (Exception e) {
             e.printStackTrace();
             }


}

}

事情是当我执行上面的程序时,我相信它会执行一个shell脚本并且那个shell脚本会等待用户输入,但它只是打印当前目录然后退出。有没有办法做到这一点,或者在java中根本不可能?

提前致谢

【问题讨论】:

标签: java runtime.exec


【解决方案1】:

它打印当前目录并退出的原因是因为您的 java 应用程序退出了。您需要为您创建的进程的输入和错误流添加一个(线程)侦听器,并且您可能希望在进程的输出流中添加一个 printStream

示例:



            proc = Runtime.getRuntime().exec(cmds);
            PrintStream pw = new PrintStream(proc.getOutputStream());
            FetcherListener fl = new FetcherListener() {

                @Override
                public void fetchedMore(byte[] buf, int start, int end) {
                    textOut.println(new String(buf, start, end - start));
                }

                @Override
                public void fetchedAll(byte[] buf) {
                }           
            };
            IOUtils.loadDataASync(proc.getInputStream(), fl);
            IOUtils.loadDataASync(proc.getErrorStream(), fl);
            String home = System.getProperty("user.home");
            //System.out.println("home: " + home);
            String profile = IOUtils.loadTextFile(new File(home + "/.profile"));
            pw.println(profile);
            pw.flush();

要运行它,您需要下载我的 sourceforge 项目:http://tus.sourceforge.net/,但希望代码 sn-p 足够有指导意义,您可以适应 J2SE 和您正在使用的任何其他东西。

【讨论】:

  • 您能否发布一些示例代码或网页链接,并通过示例详细说明。
  • 我尝试使用您的代码并从 SVN 下载您的源代码,发生的情况是它等待输入,而且我能够在控制台上输入输入,但它永远不会将该输入传递给 shell 脚本和程序保持在执行。理想情况下,它的行为方式是在输入名称后 shell 脚本应该打印名称并且程序应该执行。
  • 所以一旦你得到数据,通过 printWriter / printStream 将其写入 shell 脚本,然后使用 flush()
  • 感谢您的帮助,但我只是有点困惑如何获取用户正在输入的数据。
  • 其实我只是在寻找一种方法来获取用户输入的数据,我应该使用 DataFetcher 类,如果是,如何使用它获取数据?
【解决方案2】:

如果您使用 Java ProcessBuilder,您应该能够获取您创建的流程的输入、错误和输出流。

这些流可用于获取来自流程的信息(例如输入提示),但也可以写入它们以将信息直接放入流程中。例如:

InputStream stdout = process.getInputStream ();
BufferedReader reader = new BufferedReader (new InputStreamReader(stdout));

String line;
while(true){
    line = reader.readLine();
    //...

这将直接为您提供流程的输出。我自己没有做过,但我很确定 process.getOutputStream() 为您提供了一些可以直接写入以将输入发送到进程的内容。

【讨论】:

    【解决方案3】:

    Runtime.exec 运行交互式程序(例如sudo)的问题在于它将它们的标准输入和标准输出连接到管道而不是它们需要的控制台设备。您可以通过redirecting the input and output to /dev/tty 使其工作。

    您可以使用新的ProcessBuilder 类实现相同的行为,使用ProcessBuilder.Redirect.INHERIT 设置重定向。

    【讨论】:

      【解决方案4】:

      请注意,您可以将输入从 Java 发送到您的脚本。但是,如果您要从 Java 执行外部脚本,我强烈建议您查看 Commons Exec:

      Commons Exec homepage

      Commons Exec API

      【讨论】:

        猜你喜欢
        • 2017-02-13
        • 2015-12-26
        • 2010-10-10
        • 2013-06-19
        • 2019-09-18
        • 1970-01-01
        • 1970-01-01
        • 2012-07-03
        • 1970-01-01
        相关资源
        最近更新 更多