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

时间:2015-01-09 20:19:54

标签: java linux bash shell

我正在使用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

当我直接使用key和value执行jj.sh时,它会给我正确的值,即文件名。 但是对于java,它给出了结果为ls -1结果(意味着java忽略了'|'之后的命令)。当我传递用波形符号`分隔的键值时,它只显示完整的键值,即ls -1|tail -1

如何使用java

执行完整命令

2 个答案:

答案 0 :(得分:8)

这不起作用的主要原因是`$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 

答案 1 :(得分:0)

正如其他海报已经指出的那样,子过程不是在shell中启动的,所以不会解释她的爆炸。

通过在jj.sh中显式启动shell中第二个参数的评估,我得到了你的例子:

value=`sh -c "$2"` 

不好,但有效。

其他选项可能是在shell中显式启动脚本,模仿sh-bang:

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