我有一个使用Maven(作为jar)构建的Spark Streaming应用程序,并使用spark-submit
脚本进行部署。应用程序项目布局遵循标准目录布局:
myApp
src
main
scala
com.mycompany.package
MyApp.scala
DoSomething.scala
...
resources
aPerlScript.pl
...
test
scala
com.mycompany.package
MyAppTest.scala
...
target
...
pom.xml
在DoSomething.scala
对象中,我有一个尝试执行Perl脚本的方法(让我们称之为doSomething()
) - aPerlScript.pl
(来自resources
}文件夹) - 使用scala.sys.process.Process
并将两个参数传递给脚本(第一个是用作输入的二进制文件的绝对路径,第二个是生成的输出文件的路径/名称)。我打电话给DoSomething.doSomething()
。
问题是我无法访问脚本,没有访问绝对路径,相对路径,getClass.getClassLoader.getResource,getClass.getResource,我在pom.xml
中指定了资源文件夹。我没有尝试成功。我不知道如何找到我放在src / main / resources中的东西。
我将不胜感激。
侧面说明:
getClass.getClassLoader.getResource
"标准"访问资源的方法我发现实际的类路径是spark-submit
脚本的一个。答案 0 :(得分:2)
有一些解决方案。最简单的方法是使用Scala的流程基础架构:
import scala.sys.process._
object RunScript {
val arg = "some argument"
val stream = RunScript.getClass.getClassLoader.getResourceAsStream("aPerlScript.pl")
val ret: Int = (s"/usr/bin/perl - $arg" #< stream).!
}
在这种情况下,ret
是流程的返回代码,流程的任何输出都会定向到stdout
。
第二个(更长的)解决方案是将文件aPerlScript.pl
从jar文件复制到某个临时位置并从那里执行。此代码段应该包含您需要的大部分内容。
object RunScript {
// Set up copy destination from the Java temporary directory. This is /tmp on Linux
val destDir = System.getProperty("java.io.tmpdir") + "/"
// Get a stream to the script in the resources dir
val source = Channels.newChannel(RunScript.getClass.getClassLoader.getResourceAsStream("aPerlScript.pl"))
val fileOut = new File(destDir, "aPerlScript.pl")
val dest = new FileOutputStream(fileOut)
// Copy file to temporary directory
dest.getChannel.transferFrom(source, 0, Long.MaxValue)
source.close()
dest.close()
}
// Schedule the file for deletion for when the JVM quits
sys.addShutdownHook {
new File(destDir, "aPerlScript.pl").delete
}
// Now you can execute the script.
此方法允许您将本机库捆绑在JAR文件中。复制它们允许在运行时加载库以用于您计划的任何JNI恶作剧。