在Java中执行Shell脚本并读取输出

5

我正在使用以下方法在Java中执行Shell脚本:

public static void main(String ar[])
{
  //key value are being read from properties file, here I am assigning the sample values      directly

   key=mine
   value="ls-1|tail-1"


  String[] cmd = { "jj.sh" , key,value};
  Process script_exec = Runtime.getRuntime().exec(cmd);
  script_exec.waitFor();
  if(script_exec.exitValue() != 0){
   System.out.println("Error while executing script");

  BufferedReader stdInput = new BufferedReader(new
                InputStreamReader(script_exec.getInputStream()));

  while ((s = stdInput.readLine()) != null) {
                System.out.println(s);
            }
}

jj.sh文件包含以下值:

#!/bin/sh

key=$1
value=`$2` 
echo $value

当我直接使用密钥和值执行jj.sh时,它会给出正确的值,即文件名。 但是使用Java时,它将结果作为ls -1结果(这意味着Java忽略了“|”之后的命令)。当我传递用波浪线“~”分隔的密钥值时,它只显示完整的键值,即ls -1 | tail -1
如何使用Java执行完整命令?

1
当您直接运行jj.sh时,该如何操作? - that other guy
您可能需要使用所期望的shell的完整路径作为第一个参数,因为哈希-叹号对于Java生成的执行shell可能没有意义。此外,您需要仔细注意某些字符的转义方式,因为这些内容被解析了多次。 - user1531971
这个在Java代码中运行shell脚本并传递参数的问题可能对你有所帮助。特别是,从runtime.exec()转换为process.start()。而且,这两者都不是shell; 你应该调用shell并将脚本作为参数传递给它。 - Stephen P
@thatotherguy:我运行了 sh jj.sh,我的命令是 "ls -1|tail -1"。 - Learner
1
@Jagdeep 当我使用你的脚本运行该命令时,我得到了“ls: invalid option -- '|' Try `ls --help' for more information.”的错误提示。当你复制并粘贴你的命令时,你得到了什么结果?请确保实际上将命令复制并粘贴到终端中,而不是运行你认为等效的命令。 - that other guy
显示剩余3条评论
2个回答

13

这个方法不能工作的主要原因是`$2``ls -1 | tail -1`不相同,即使$2被设置为该字符串。

如果您的脚本接受一个包含要执行的命令的文字字符串,您可以使用eval来执行它。

我创建了一个完整的示例,请复制粘贴并验证它是否有效,然后再尝试将其应用到您自己的代码中。这是Test.java

import java.io.*;

public class Test {
  public static void main(String[] args) throws Exception {
    String[] command = { "./myscript", "key", "ls -t | tail -n 1" };
    Process process = Runtime.getRuntime().exec(command);
    BufferedReader reader = new BufferedReader(new InputStreamReader(
        process.getInputStream()));
    String s;
    while ((s = reader.readLine()) != null) {
      System.out.println("Script output: " + s);
    }
  }
}

关于 myscript

#!/bin/bash
key="$1"
value=$(eval "$2")
echo "The command  $2  evaluated to: $value"

以下是如何单独运行myscript的方法:

$ ls -t | tail -n 1
Templates

$ ./myscript foo 'ls -t | tail -n 1'
The command  ls -t | tail -n 1  evaluated to: Templates

这是运行Java代码的结果:
$ javac Test.java && java Test
Script output: The command  ls -t | tail -n 1  evaluated to: Templates 

0

正如其他帖子已经指出的那样,子进程没有在shell中启动,因此she-bang没有被解释。

我通过在jj.sh中显式地启动第二个参数的评估来使您的示例工作:

value=`sh -c "$2"` 

不太好看,但是能用。

另一个选择可能是在shell中显式地启动脚本,模拟sh-bang:

String[] cmd = { "/bin/sh", "jj.sh" , key,value};

它实际上会运行she-bang。尝试编写一个仅包含she-bang和ps $$的shell脚本,并通过(已更正的)上述程序运行它。 - RealSkeptic

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接