3

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

オブジェクトには、 (フォルダーから) Perl スクリプトを実行しようとするDoSomething.scalaメソッド (と呼びましょう) があります。2 つの引数を使用してスクリプトに渡します (最初の引数は、バイナリ ファイルへの絶対パスとして使用されます)。入力、2 番目は生成された出力ファイルのパス/名前です)。私はそれから電話します。doSomething()aPerlScript.plresourcesscala.sys.process.ProcessDoSomething.doSomething()

問題は、絶対パス、相対パス、getClass.getClassLoader.getResource、getClass.getResource ではなく、スクリプトにアクセスできなかったことpom.xmlです。私の試みはどれも成功しませんでした。src/main/resources に置いたものを見つける方法がわかりません。

どんな助けにも感謝します。

補足:

  • ワークフローのこのステップでは、バイナリ ファイルを入力および出力として処理する必要があるため、Spark パイプの代わりに外部プロセスを使用します。
  • Spark-streaming 1.1.0、Scala 2.10.4、および Java 7 を使用しています。Eclipse (Kepler) 内から「Maven install」を使用して jar をビルドします。
  • getClass.getClassLoader.getResource「標準」メソッドを使用してリソースにアクセスすると、実際のクラスパスがスクリプトspark-submitのものであることがわかります。
4

1 に答える 1

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.pl2 つ目の (より長い) 解決策は、ファイルを 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 のいたずらに対して実行時にライブラリをロードできます。

于 2014-10-05T16:14:15.340 に答える