我不知道如何以简单的方式重现我的问题。
我有一个演员,通过' sys.process'执行外部命令。封装
object FileHelper {
def downloadFile(url: String, filename: String): Either[String, Unit] = {
println(s"MyThread: ${Thread.currentThread().getName}")
util.Try {
import scala.language.postfixOps
new URL(url) #> new File(filename) !
} match {
case util.Failure(err) => Left(s"Download error: $err")
case util.Success(code) => if (code != 0) Left("Can't download file") else Right({})
}
}
}
所以当我在演员中调用dowloadFile时,Try语句不起作用!
router MyThread: app-akka.actor.default-dispatcher-3
router[ERROR] Exception in thread "Thread-10" java.io.FileNotFoundException: /home/alex/dumpss/456.tar.bz2 (No such file or directory)
router[ERROR] at java.io.FileOutputStream.open0(Native Method)
router[ERROR] at java.io.FileOutputStream.open(FileOutputStream.java:270)
router[ERROR] at java.io.FileOutputStream.<init>(FileOutputStream.java:213)
router[ERROR] at scala.sys.process.ProcessBuilderImpl$FileOutput$$anonfun$$lessinit$greater$3.apply(ProcessBuilderImpl.scala:33)
router[ERROR] at scala.sys.process.ProcessBuilderImpl$FileOutput$$anonfun$$lessinit$greater$3.apply(ProcessBuilderImpl.scala:33)
router[ERROR] at scala.sys.process.ProcessBuilderImpl$OStreamBuilder$$anonfun$$lessinit$greater$4.apply(ProcessBuilderImpl.scala:38)
router[ERROR] at scala.sys.process.ProcessBuilderImpl$OStreamBuilder$$anonfun$$lessinit$greater$4.apply(ProcessBuilderImpl.scala:38)
router[ERROR] at scala.sys.process.ProcessBuilderImpl$ThreadBuilder$$anonfun$1.apply$mcV$sp(ProcessBuilderImpl.scala:58)
router[ERROR] at scala.sys.process.ProcessImpl$Spawn$$anon$1.run(ProcessImpl.scala:23)
正如您所看到的,外部命令已在线程&#39; Thread-10&#39;中执行。但尝试在app-akka.actor.default-dispatcher-3&#39;中捕获异常。
答案 0 :(得分:1)
使用scala进程api,url下载和文件重定向由线程而不是实际进程实现:https://github.com/scala/scala/blob/2.12.x/src/library/scala/sys/process/ProcessBuilderImpl.scala#L31-L64
所以,当这一行被执行时,
new URL(url) #> new File(filename) !
生成另外两个线程,一个用于下载url并将结果写入管道,另一个从管道读取并将其读取的任何内容写入文件。并且父线程(actor正在运行)等待它们的退出值,并相应地返回它们中的任何一个:https://github.com/scala/scala/blob/2.12.x/src/library/scala/sys/process/ProcessImpl.scala#L151
不幸的是,始终忽略文件重定向的退出值。因此,您无法通过检查管道的返回代码来判断操作是否成功。 https://github.com/scala/scala/blob/2.12.x/src/library/scala/sys/process/ProcessBuilderImpl.scala#L39
您可以在commons-io库的帮助下完成工作,而不是使用scala进程api:
Try {
IOUtils.copy(url.openStream, new FileOutputStream(file))
} match {
case Success(_) => ...
case Failure(ex) => ...
}