【问题标题】:Unable to run UNIX command from Java program无法从 Java 程序运行 UNIX 命令
【发布时间】:2013-07-02 23:28:16
【问题描述】:

我正在尝试创建一个 java 程序,该程序接受一些用户输入变量并将它们传递给 perl 脚本(它实际上在 perl 脚本中找到某个字符串并将其替换为用户输入变量)。代码如下:

    String sedMain = "sed -e ";
    String sedFirstLine = "'s/AAA/"+newFirstLine+"/' -e ";
    String sedNewCntr = "'s/BBB/"+newCntr+"/' -e ";
    String sedNewSpacing = "'s/SPACE/"+newSpacing+"/' -e ";
    String sedNewDmax = "'s/MAX/"+newDmax+"/'";
    String sedFile = " /filepath/myperlscript.pl >  /filepath/myNEWperlscript.pl";
    String sedCommand=sedMain+sedFirstLine+sedNewCntr+sedNewSpacing+sedNewDmax+sedFile;
    System.out.println("SED COMMAND: "+sedCommand);
    String testRun = "touch /filepath/hello.txt";
    Process runSedCommand;
    runSedCommand = Runtime.getRuntime().exec(sedCommand);

我使用的是 IDE,当 sed 命令打印到控制台时,它看起来是正确的。我从控制台复制了 sed 命令并从终端运行它,它工作正常。我写了字符串“testRun”来查看Java中的进程是否有问题,它创建了文件“hello.txt”。但是由于某种原因,我的程序没有创建输出 perl 文件“myNEWperlscript.pl”。我很困惑为什么这不起作用。有人可以帮忙吗?

【问题讨论】:

  • exec() 将带有程序名称和参数的 String[] 作为其元素,但是您将所有内容连接到一个字符串中,因此有效地丢失了参数。
  • 所以我应该只写一个包含所有元素的字符串吗?
  • 不,你需要创建一个字符串数组
  • 只是出于好奇,为什么当我执行“testRun”字符串而不是“sedCommand”字符串时,它起作用了? testRun 不是字符串数组。
  • 还有一个 exec() 版本,它接受一个不带参数的命令字符串,尽管 touch 是如何得到一个参数的有点神秘。顺便说一句,你的输出的 shell 重定向可能不起作用,因为你没有调用 shell。

标签: java unix sed


【解决方案1】:

exec() 采用带有程序名称和参数的 String[] 作为其元素,但是您将所有内容连接到一个 String 中,因此有效地丢失了参数。

试试这样的:

String[] cmd = {"sed", "first argument", "second argument"};
Runtime.getRuntime().exec(cmd);

【讨论】:

    【解决方案2】:

    使用

    exec(String[] cmdarray) 
    

    签名。 命令是 sed,-e 是一个参数,'s/AAA/\n/' 是另一个参数,依此类推。所以你会有

    String[] command = new String[] {"sed", "-e", "s/AAA/\n/", "next parameter without single quotes", , "next parameter without quotes..."}
    Runtime.getRuntime.exec(command);
    

    这是您的参数在传递到 shell 的过程中得到良好格式化的唯一方法,否则可能会发生奇怪的 sruff,因为字符串上第一个标记之后的任何引号都将被视为一个参数,因此可以转义引号诸如此类的事情

    【讨论】:

    • 其实不涉及shell,除非执行的命令是shell。
    • 请澄清一下,如何从JVM创建子进程?
    • 通过向内核发出系统调用。外壳不是必需的——外壳只是一个程序,它可以让您更方便地启动程序、将它们的输入和输出管道串在一起等,但最终会尽可能地使用对内核的系统调用。例如,在这个问题中管道输出 sed 的尝试取决于有一个 shell,但没有调用任何 shell。所以发布者要么需要将 sed 的输出捕获到一个文件中,要么启动一个 shell 并告诉它启动 sed 并将输出通过管道传输到一个文件。
    • 感谢解答,所以java中使用exec时不能使用管道和重定向?
    • 好吧,除非您执行 shell,否则无法使用创建它们的 shell 语法。剩下的选择是自己做一个 shell 来设置它们,或者执行一个 shell 并尝试在命令行上告诉它你想要它做什么,或者执行一个 shell 并将命令传递到它的标准输入中。跨度>
    猜你喜欢
    • 2021-10-26
    • 2012-04-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-26
    相关资源
    最近更新 更多