【问题标题】:unable to run ksh script from java: java.io.IOException: .: not found无法从 java 运行 ksh 脚本:java.io.IOException: .: not found
【发布时间】:2010-10-06 11:32:05
【问题描述】:

我尝试从 java 代码运行 shell 脚本,但我遇到了问题。该脚本在 batchstart.sh 文件中 -

#!/bin/ksh
export DISPLAY=:0.0

现在脚本在命令行上运行一个点 -- 。批处理启动.sh

如何从 java 运行它?我的java代码如下。它抛出以下异常 -

java.io.IOException: .: 未找到 在 java.lang.UNIXProcess.forkAndExec(本机方法) 在 java.lang.UNIXProcess.(UNIXProcess.java:102) 在 java.lang.ProcessImpl.start(ProcessImpl.java:65) 在 java.lang.ProcessBuilder.start(ProcessBuilder.java:451) 在 java.lang.Runtime.exec(Runtime.java:591) 在 java.lang.Runtime.exec(Runtime.java:429) 在 SetDisplay.main(SetDisplay.java:12)
import java.io.*;

public class SetDisplay {

   public static void main(String[] args) {

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

       try {
           proc = Runtime.getRuntime().exec(". batchstart.sh", null, wd);
       } catch (Exception e) {
           e.printStackTrace();
       }
   }
}

如何让 shell 脚本运行?

我也尝试了以下代码,但也不起作用。

File wd = new File("/bin"); 
System.out.println(wd); 
Process proc = null; 
try { 
  proc = Runtime.getRuntime().exec("/bin/bash", null, wd); 
} 
catch (IOException e) { 
  e.printStackTrace(); 
} 
if (proc != null) { 
  BufferedReader in = new BufferedReader(new InputStreamReader(proc.getInputStream())); 
  PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(proc.getOutputStream())), true); 
  out.println("cd /home/"); 
  out.println(". batchstart.sh"); 
  out.println("exit"); 
  try { 
    String line; 
    while ((line = in.readLine()) != null) { 
      System.out.println(line); 
    } 
    proc.waitFor(); 
    in.close(); 
    out.close(); 
    proc.destroy(); 
  } 
  catch (Exception e) { 
    e.printStackTrace(); 
  } 
}

【问题讨论】:

    标签: java unix shell


    【解决方案1】:

    从命令行运行时,在脚本开头使用一个点表示该脚本应该在 当前 环境中运行,而不是生成新的子 shell 并使用新的 当前环境的副本。这允许您导出环境变量的新值,以供稍后从同一交互式 shell 运行的命令使用。

    显然,这种技术只有在您从实际的 shell 运行 batchstart.sh 脚本时才有效。 Java 不知道这种机制是如何工作的,因此点对它没有任何意义。脚本无法修改调用它的 Java 进程的环境。

    如果您的目标是更改 Java 进程运行的其他命令的 DISPLAY 环境变量的值,请考虑使用 ProcessBuilder 类为子进程指定新环境。 Java 不包含在其自身环境中修改变量的内置方法。

    【讨论】:

      【解决方案2】:

      源命令 (".") 是一个内置的 shell。您必须显式运行/bin/ksh,将您的脚本名称作为参数传递(后跟任何脚本参数)。

      如果您需要获取脚本的来源,则会遇到更大的问题。这通常意味着环境更改发生在当前 shell 的上下文中,而不是子 shell。

      这不适用于 Java,因为 Java 不是 shell。您需要弄清楚如何使用 Java 更改环境。

      当然,如果我错了,并且该脚本还有更多仅设置 DISPLAY 的内容,它可能会按建议工作。

      您将不得不使用的方法取决于您要实现的目标(如“您是否使用 exec() 运行其他依赖于设置的 DISPLAY 的程序?”或“您的 Java 程序是否需要要设置 DISPLAY 吗?”)。

      如果,正如您在评论中所述,只有您的 Java 程序需要 DISPLAY 设置,请在程序运行之前将其设置在外部。创建一个设置 DISPLAY 变量的 cmd(或 bash)文件然后调用 JRE 来运行您的程序。

      #/bin/ksh
      export DISPLAY-:0.0
      /usr/bin/jre/java your_program blah.blah.blah
      

      我还会修改您的 main() 以检查它是否设置为某个值,如果没有,则优雅地退出:

      if (System.getenv ("DISPLAY") == null)
          // doesn't exist, exit gracefully.
      

      【讨论】:

      • 我的java程序只需要设置DISPLAY。那么有没有什么方法可以让我从 java 运行脚本?
      • 所以你的意思是没有办法让“export DISPLAY=:0.0”从 java 中工作?
      • 不,请参阅更新。您的基本问题是您从 Java 运行的任何外部操作都不会影响 Java 环境。而且,最重要的是,我不相信 Java 提供了 setenv()。
      • 是的,这就是我的意思,Vicky(很遗憾)。
      • 您需要设置它是因为您正在调用 X 例程,还是您的 Java 代码只是使用 getenv() 来获取 DISPLAY 并使用它?
      【解决方案3】:

      句号“.”是一个内置的 shell,并“就地”执行脚本,类似于 C/C++ 中的#include。使用 ”。”在 shell 脚本之外没有任何意义。

      如果你想运行 Java 中的脚本,你必须执行脚本解释器 (/bin/ksh):

        Runtime.getRuntime().exec("/bin/ksh batchstart.sh", ...)
      

      但请注意,这在语义上并不等效,因为您将 batchstart.sh 作为子进程执行而不是获取它。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-09-14
        • 2011-06-15
        • 2021-05-12
        • 2014-04-17
        相关资源
        最近更新 更多