【问题标题】:executing the customs command on linux with process builder in java在 linux 上使用 java 中的 process builder 执行 custom 命令
【发布时间】:2014-08-28 06:27:48
【问题描述】:

我已经为这个问题苦苦挣扎了一段时间,但我似乎无法解决它。我已经尝试ProcessBuilder 在 linux 终端上执行自定义命令,但它不起作用

实际上我有两个.sh 文件setProto.sh and setTls.sh 用于设置环境的文件。所以为了执行命令,我需要先为每个linux终端实例运行这两个文件。只有这样我们才能能够在应该运行 .sh 文件的 Linux 终端的同一实例上运行自定义命令 anloss。由于某种原因,我无法使其工作我的代码中的错误是什么?这是代码。

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.ProcessBuilder.Redirect;

public class EngineTest {

    public static void main(String[] args) {
        try {
            ProcessBuilder builder = new ProcessBuilder(
                    "/. setProto.sh",
                    "/. setTls.sh",
                    "/anloss -i ${TOOL_INPUT}/census_10000_col5.csv  -d ${TOOL_DEF}/attr_all_def.txt -q k=14,dage=2 -g ${TOOL_RES}/census_100_col8_gen.csv");
            builder.directory(new File(System.getenv("HOME") + "/PVproto/Base"));
            File log = new File("log");
            builder.redirectErrorStream(true);
            builder.redirectOutput(Redirect.appendTo(log));
            Process process = builder.start();

            BufferedReader bufferedReader = new BufferedReader(
                    new InputStreamReader(process.getInputStream()));
            String line = "";
            String output = "";
            while ((line = bufferedReader.readLine()) != null) {
                output += line + "\n";
            }
            System.out.println(output);
            int exitValue = process.waitFor();
            System.out.println("\n\nExit Value is " + exitValue);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}

【问题讨论】:

    标签: java linux shell


    【解决方案1】:

    默认情况下,进程不会在 shell 上下文中执行;因此您的 shell 脚本无法按照您尝试的方式执行。

    ProcessBuilder pb =
        new ProcessBuilder( "/bin/bash",
                            "-c", 
                            ". setProto.sh && . setTls.sh && /anloss -i ${TOOL_INPUT}/census_10000_col5.csv  -d ${TOOL_DEF}/attr_all_def.txt -q k=14,dage=2 -g ${TOOL_RES}/census_100_col8_gen.csv" );
    

    我不确定/anloss - 命令位于root 的家/ 是不寻常的。 (另外,你在 shell 脚本前面的 /. - 它们应该实现什么?)

    稍后

    确保将/anloss替换为绝对路径名相对于$HOME/PVproto/Base的相对路径名,例如,如果它在此目录中,请使用@987654327 @,如果在$HOME/PVproto/Base/SomeSub,则使用SomeSub/anloss

    另外,如果 setProto.sh 和 . setTls.sh 不在$HOME/PVproto/Base 中,请使用适当的绝对或相对路径名。如果是,请使用./setProto.sh./setTls.sh 以避免依赖环境变量PATH 的设置。

    【讨论】:

    • /.对于脚本是在当前目录上运行并且 /anloss 不在根目录中。如果你看到我的代码,我已经添加了 builder.directory(new File(System.getenv("HOME") + "/PVproto/Base"));这是所有脚本和命令必须运行的路径。如果我犯了任何错误,请告诉我。
    • 我已经尝试过你的方法,但它抛出错误“无法运行程序/bash/bin”(在目录“/home/cloudera/PVproto/Base”中):错误=2,没有这样的文件或目录
    • 该程序被称为/bin/bash (not /bash/bin),如果它是 Linux,它必须存在。你也可以使用/bin/sh
    • 设置一个工作目录并没有影响你认为需要指定程序错误执行路径名的方式。如果将工作目录设置为 /home/henry,则可以使用 ./aProgInHenry.exe 在此目录中执行文件,但如果程序位于其他位置,请指定绝对路径名。 /anloss一个绝对路径名,指示系统进入根目录。
    • /. 开始一个命令来“在当前目录上运行”——你从哪里得到这个想法? /. 是指根目录的绝对路径名,即/。 (在 shell 提示符下尝试 ls /.。)如果这是第一个在命令中,它只会尝试调用名为 / 的程序,这当然是无稽之谈。
    【解决方案2】:

    我认为您需要使用 Runtime.exec() 在 linux 上执行命令。我想你是在需要运行 linux 脚本的 linux 机器上执行你的 java 代码。

    下面的代码 sn-p 将帮助您解决它。

    Process process = Runtime.getRuntime().exec(scriptWithInputParameters);
    int exitCode = process.waitFor();
    if (exitCode == 0) {
        System.out.println("Executed successfully");
    }
    else {
      System.out.println("Failed ...");
    }
    


    请注意,您需要在不同的线程中处理错误和输出流,以避免缓冲区溢出。

    如果上述方法对您有用,那么this article 将进一步帮助您

    【讨论】:

      猜你喜欢
      • 2021-12-10
      • 2017-11-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-10-09
      • 2011-06-11
      相关资源
      最近更新 更多