1

我有一个普通的 java 应用程序,它有一个调用 shell 脚本文件的主类src/main/resources/*.sh

我正在使用 Runtime.getRuntime().exec(cmd) 来执行脚本。

String cmdPath = new this.getClass().getResource("/XXXX.sh").getPath()
String[] cmd = { "bash", cmdPath };

我收到退出代码 127。

1) 使用 java -jar xxx.jar 运行

2)sh文件的文件权限是-rw-rw-r--

如何获得脚本文件的文件权限来执行?

脚本文件位于 src/main/resource/

使用maven-jar插件打包jar,脚本文件进入根目录

jar /-com -software -cmd.sh

尝试使用自定义脚本的 maven 程序集插件为 {basedir} 下的所有文件授予 755 权限(未在任何地方定义)。它不起作用

<assembly
        xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.3 http://maven.apache.org/xsd/assembly-1.1.3.xsd">
    <id>ourAssembly</id>
    <formats>
        <format>jar</format>
    </formats>

    <fileSets>
        <fileSet>
            <directory>${basedir}</directory>
            <includes>
                <include>**/*</include>
            </includes>
            <fileMode>0755</fileMode>
        </fileSet>
    </fileSets>
4

2 回答 2

2

getPath()URL的方法没有返回有效的文件名。URL 的“路径”只是权限之后的部分,不包括任何查询或片段。URL 中不允许使用很多字符,因此它们被百分比转义,并且getPath()将返回带有这些转义的字符串。

此外,.jar 条目根本不是文件,它只是 .jar 文件中表示压缩数据的字节子序列。要执行它,您需要将它复制到一个真实的文件中,然后执行它。

像这样的东西:

Path script = Files.createTempFile(null, ".sh",
    PosixFilePermissions.asFileAttribute(
        PosixFilePermissions.fromString("rw-rw-r--")));

try (InputStream embeddedScript =
    this.getClass().getResourceAsStream("/XXXX.sh")) {

    Files.copy(embeddedScript, script, StandardCopyOption.REPLACE_EXISTING);
}

String[] cmd = { "bash", script.toString() };

完成后,您应该删除副本:

ProcessBuilder builder = new ProcessBuilder(cmd);
builder.inheritIO();

Process process = builder.start();
process.waitFor();

Files.delete(script);
于 2019-09-03T15:00:15.520 回答
0

如果您出于某种原因不想创建临时文件,您也可以执行该过程并将 InputStreamgetResourceAsStream作为标准输入传递。

这是 Scala,其 ProcessBuilder API 稍有不同,并使用了一种时髦的语法来传递输入流,但适用相同的原则

import scala.sys.process.Process
object Sh {
  def call(resourcePath: String, args: Seq[String]): Int = {
    (Process("sh", Seq("-s", "--") ++ args) #< getClass.getResourceAsStream(resourcePath)).run().exitValue()
  }
}

如果没有-s参数,则参数将指向 sh 本身,而不是您的脚本。

此外,这种方法仅适用于实际的 shell 脚本,如果您#!/usr/bin/python在顶部添加sh会忽略它。exec() 系统调用是处理 #! 我们不能在没有 JNI 或一些 hack 的情况下从 Java 调用它。

于 2020-06-06T18:22:21.140 回答