【问题标题】:Java Execute Shell Script Bundled within JAR [duplicate]JAR中捆绑的Java执行Shell脚本[重复]
【发布时间】:2012-10-04 05:11:34
【问题描述】:

可能重复:
Executing a shell script inside a jar file. How to extract?

我有一个 shell 脚本打包到我的 JAR 文件中的“引擎”包中。

在我的程序中,我正在使用 Process 和 ProcessBuilder 运行 shell 命令。这一切都很好。

如果我在我的计算机上指定了 shell 脚本的路径,那么程序就可以正常工作。但是,如果我将 shell 脚本打包到我的 JAR 中并像这样访问它:

scriptLocation = this.getClass().getResource("/engine/shell-script.sh").toString();

然后运行程序,我得到以下错误:

java.io.IOException: Cannot run program "file:/Users/USERNAME/Desktop/Application-Name.jar!/engine/shell-script.sh": error=2, No such file or directory
    at java.lang.ProcessBuilder.start(ProcessBuilder.java:460)
    at java.lang.Runtime.exec(Runtime.java:593)
    at java.lang.Runtime.exec(Runtime.java:431)
    at java.lang.Runtime.exec(Runtime.java:328)
    at engine.Download$1.run(Download.java:39)
    at java.lang.Thread.run(Thread.java:680)
Caused by: java.io.IOException: error=2, No such file or directory
    at java.lang.UNIXProcess.forkAndExec(Native Method)
    at java.lang.UNIXProcess.<init>(UNIXProcess.java:53)
    at java.lang.ProcessImpl.start(ProcessImpl.java:91)
    at java.lang.ProcessBuilder.start(ProcessBuilder.java:453)
    ... 5 more

我开始认为这无法做到,我非常想提供这个 shell 脚本作为应用程序的一部分,可以做到吗?

提前谢谢大家。

======== 更新 ==========

我最终解决了这个问题。 Shell 不能在 JAR 包中执行脚本,它不是关于 Java,而是关于 shell。我通过执行以下操作解决了这个问题:

Java 有一个 createTempFile() 方法(具有在应用程序终止后删除文件的选项),调用它,并在 JAR 包中写入要访问此临时文件的文件。然后,您在本地文件系统上拥有 shell 脚本,并且能够执行该脚本。

【问题讨论】:

    标签: java shell


    【解决方案1】:

    最简单的解决方案是让您的应用程序将 shell 脚本提取到一个临时位置并从那里执行它。

    您可以通过调用File.createTempFile(String, String) 在Java 中生成一个临时文件。

    您可以做的另一件事是将脚本的内容(从您的 jar 加载)作为 shell 的标准输入传递。

    为了简化,如果我有一个存档 a.zip 包含一个脚本 a.sh,这将执行它:

    $ unzip -p a.zip a.sh | bash
    

    从 Java 程序中,您可以执行以下操作:

    import java.io.*;
    class Test{
    
      public static void main(String[]args) throws Exception {
    
        StringBuilder sb = new StringBuilder();
    
        // You're not strictly speaking executing a shell script but
        // rather programatically typing commands into the shell
        // sb.append("#!/bin/bash\n");
        sb.append("echo Hello world!\n");
        sb.append("cd /tmp\n");
        sb.append("echo current directory: `pwd`\n");
    
        // Start the shell
        ProcessBuilder pb = new ProcessBuilder("/bin/bash");
        Process bash = pb.start();
    
        // Pass commands to the shell
        PrintStream ps = new PrintStream(bash.getOutputStream());
        ps.println(sb);
        ps.close();
    
        // Get an InputStream for the stdout of the shell
        BufferedReader br = new BufferedReader(
            new InputStreamReader(bash.getInputStream()));
    
        // Retrieve and print output
        String line;
        while (null != (line = br.readLine())) {
          System.out.println("> "+line);
        }
        br.close();
    
        // Make sure the shell has terminated, print out exit value
        System.out.println("Exit code: " + bash.waitFor());
    
      }
    
    }
    

    【讨论】:

    • 我不希望将文件复制到用户的系统上,我将如何传递要在程序中使用的脚本内容?
    • 在我看来非常有趣的解决方案,感谢分享
    【解决方案2】:

    这不是关于 Java,而是关于 shell。据我所知,shell 解释器无法执行驻留在 zip 文件中的脚本。所以你有几个选择:

    1. 从您的 java 程序中将 shell 脚本作为文本文件读取。 创建一个临时文件(在临时目录或任何其他相关位置并在那里复制文件的内容。然后使用此临时脚本调用 shell 解释器。 我相信这是最好的方法

    2. 由于 jar 是一个 zip,您可以从 shell 中解压缩它,找到一个脚本并执行 shell。同样,这更尴尬而且相当错误,但从技术上讲它应该可以工作。

    3. 如果您的脚本中没有低级别的东西,您可以考虑将逻辑重写为 groovy 脚本(也许您会发现有用的 groosh 项目)。 然后从内存而不是文件中调用 groovy 代码。

    好吧,我没有想法,如果我是你,我会实施第一个解决方案 :) 祝你好运,希望这会有所帮助

    【讨论】:

    • 感谢您的回答,我会看看如何将 shell 脚本从 jar 文件中提取到临时位置,然后从那里提取,您知道我该怎么做吗?的任何链接?感谢您的回答!
    • 正如我在别处提到的,你可以这样做: unzip -p JARFILE SCRIPTFILE |重击。这实际上会从 jar 中提取文件,但实际上不会创建文件。
    • 我希望我能早两天看到这个答案:(
    • 如果有人必须从 java 程序运行 shell 脚本,第一个解决方案是最容易实现的。这是一个示例实现:stackoverflow.com/a/56557639/2563765
    【解决方案3】:

    我通常只是...

    $ jar xf myapp.jar run.sh && ./run.sh && rm run.sh
    

    ...如果需要,您可以从 Runtime.exec() 调用它。

    【讨论】:

    • 如果该 jar 文件是从命令行运行的,但它是一个可运行的 jar 文件,那就太好了
    • 通过 Runtime.exec() 执行它应该能够解决这个问题,尽管它确实很难看。
    猜你喜欢
    • 2013-08-06
    • 1970-01-01
    • 2010-12-23
    • 1970-01-01
    • 2013-09-09
    • 1970-01-01
    • 2020-08-28
    • 1970-01-01
    • 2019-12-02
    相关资源
    最近更新 更多