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

在Java中执行shell脚本并读取输出,java,linux,bash,shell,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}; Pr

我正在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文件包含以下值

#/垃圾箱/垃圾箱
钥匙=1美元
值=`$2`
echo美元价值
当我直接使用key和value执行jj.sh时,它会给我正确的值,即文件名。 但是,对于java,它将结果作为ls-1结果提供给我(意味着java将忽略“|”之后的命令)。当我传递以波浪号`分隔的键值时,它只显示完整的键值,即
ls-1 | tail-1


如何使用java执行完整命令正如其他海报所指出的,子进程不是在shell中启动的,因此不会解释she-bang

我通过在jj.sh中显式地开始对shell中的第二个参数进行求值来实现您的示例:

value=`sh -c "$2"` 
不太好,但很管用

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

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

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

直接运行时如何运行
jj.sh
;对于Java生成的execshell来说,散列爆炸可能没有意义。此外,您还必须密切注意一些字符是如何转义的,因为这些字符会被多次解析。这个问题可能对您有所帮助。特别是,从
runtime.exec()
切换到
process.start()
。而且,两者都不是贝壳;首先,您的Java代码实际上并没有编译。您没有关闭
if
块。我允许的变量都是字符串。但是,你写的
ls-1 | tail-1
没有空格,它永远不会飞。但是,您的shell脚本实际上无法与管道一起工作。您可能正在以
jj.sh键ls-1 | tail-1
的形式运行它,它实际上运行
jj.sh键ls-1
,然后将输出传递到
tail-1
@Jagdeep当我使用脚本运行该命令时,我会得到“ls:invalid option--'|请尝试“ls--help”以获取更多信息。”。复制粘贴命令时会得到什么?确保将命令复制粘贴到终端中,不要运行您认为等效的东西。它实际上运行的是she bang。尝试编写一个只有she-bang和
ps$$
的shell脚本,并通过上面的程序(更正形式)运行它。