构建一个 jar 以包含未获得执行权限的 shell 脚本文件



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

我正在使用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 -软件 -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>

URL 的getPath()方法返回有效的文件名。 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);

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

这是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论证,args to sh本身,而不是你的脚本。

此外,此方法仅适用于实际的 shell 脚本,如果您在顶部添加了#!/usr/bin/pythonsh则会忽略它。 exec(( 系统调用是处理 #! 如果没有JNI或一些黑客,我们就不能从Java调用它。

最新更新