Linux 终端编写 Scala Spark 程序

一直使用 Windows 下的 IDEA 做 Scala Spark 程序开发,打包后用 WinSCP 上传到服务器运行,很麻烦,所以就想在 Linux 服务器上部署 Scala、SBT 来编写 Spark 程序。再编写一些简单脚本,肯定可以使编译、打包、运行一气呵成。当然了,也是有缺点的,就是没有了 IDE,写代码就困难了(哭)。还有就是 vim 的支持情况,默认是不识别 scala 文件的。

安装

从官网下载 scala 和 sbt:

  • spark 1.5 使用 scala-2.10.6
  • sbt 最新版 sbt-0.13.13.tgz

解压缩,添加到环境变量 .bash_profile

1
2
PATH=$PATH:/path/to/sbt-launcher-packaging-0.13.13/bin
PATH=$PATH:/path/to/scala-2.10.6/bin

然后source ~/.bash_profile 就可以使用 scalasbt 命令了。

SBT 配置

一个典型的sbt配置文件如下所示,采用多项目的形式,因为编写 Spark 程序通常是共用一套配置的,只是用不同的 scala 文件打不同的 jar 包而已:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
//通用配置
lazy val commonSettings = Seq(
organization := "com.zhangnew",
//项目版本
version := "1.0",
//scala版本
scalaVersion := "2.10.6",
//非托管依赖,存放 jar 包
//unmanagedBase := baseDirectory.value / "lib"
//依赖仓库
//resolvers += "twttr" at "http://maven.twttr.com"
//托管依赖,这里使用 ++= 连接列表 Seq();% "provided" 表示此jar不打入最终的jar文件内
libraryDependencies ++= Seq(
"org.apache.spark" % "spark-core_2.10" % "1.5.0" % "provided",
"org.apache.spark" % "spark-sql_2.10" % "1.5.0" % "provided",
"org.apache.spark" % "spark-hive_2.10" % "1.5.0" % "provided"
),
//打包时,排除scala类库
assemblyOption in assembly := (assemblyOption in assembly).value.copy(includeScala = false),
//打包的 jar 名称
//assemblyJarName in assembly := "target.jar",
//打包时排除 lib 下面的 jar 文件
assemblyExcludedJars in assembly := {
val cp = (fullClasspath in assembly).value
cp filter {_.data.getName == "hadoop-lzo-0.4.16.jar"}
}
)

//主目录下的 test 目录作为一个子项目
lazy val test = (project in file("test"))
// 依赖 util 这个项目
//.dependsOn(util)
.settings(
commonSettings,
//项目名称
name := "scalaSpark",
//主函数
mainClass in Compile := Some("test")
)

SBT依赖

非托管依赖

设置 jar 包所在路径为 custom_lib,默认在 lib 目录下面,可以不用设置:

1
unmanagedBase := baseDirectory.value / "custom_lib"

托管依赖

sbt 使用 Apache Ivy 来实现托管依赖:

1
2
libraryDependencies += groupID % artifactID % revision
resolvers += "twttr" at "http://maven.twttr.com"

SBT 插件

如果你的项目在 hello 目录下,如果你添加 sbt-assembly,像下面这样创建 hello/project/assembly.sbt

1
addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.14.4")

这个插件很好用,用来打包 jar 可以很好的处理各种依赖。

全局插件

可以一次给所有项目安装插件,只要在 ~/.sbt/0.13/plugins/ 中声明它们。~/.sbt/0.13/plugins/ 是一个将自己的 classpath 导出给所有项目的 sbt 构建定义。 概略地讲,在 ~/.sbt/0.13/plugins/ 中的任何 .sbt 或者 .scala 文件就和所有项目的 project/ 目录下的一样。

为了一次给所有的项目添加插件,你可以创建 ~/.sbt/0.13/plugins//build.sbt 并且添加 addSbtPlugin() 表达式。因为这样做会增加机器上的依赖,所以这个特性应该少用。

使用

命令 解释
clean 删除所有生成的文件 (在 target 目录下)。
compile 编译源文件(在 src/main/scala 和 src/main/java 目录下)。
test 编译和运行所有测试。
console 进入到一个包含所有编译的文件和所有依赖的 classpath 的 Scala 解析器。输入 :quit, Ctrl+D (Unix),或者 Ctrl+Z (Windows) 返回到 sbt。
run <参数>* 在和 sbt 所处的同一个虚拟机上执行项目的 main class。
package 将 src/main/resources 下的文件和 src/main/scala 以及 src/main/java 中编译出来的 class 文件打包成一个 jar 文件。
help <命令> 显示指定的命令的详细帮助信息。如果没有指定命令,会显示所有命令的简介。
reload 重新加载构建定义(build.sbt, project/.scala, project/.sbt 这些文件中定义的内容)。在修改了构建定义文件之后需要重新加载。
assembly 使用 assembly 插件打 jar 包。

对于有子项目的命令使用,比如当前项目下面有一个 test 项目:

  • 要运行这个项目: sbt test/run
  • 打包:sbt test/assembly

详情见文档 http://www.scala-sbt.org/0.13/docs/zh-cn/Running.html

附录

Vim Scala 高亮

使用 Vundle 安装插件:

1
Plugin 'derekwyatt/vim-scala'

SBT HTTP 代理

SBT_OPTS 需要 export,务必保证 sbt 能够读取到,为了简易,可以直接编辑 bin/sbt 文件,在开头 加上:

1
2
3
export SBT_OPTS="$SBT_OPTS -Dhttp.proxyHost=proxy.xxx.com\
-Dhttp.proxyPort=xxx\
-Dhttp.proxyUser=CHINA\\username -Dhttp.proxyPassword=password"

sbt -v # 使用-v参数,输出系统变量

hadoop-lzo time out

默认仓库无法下载 hadoop-lzo 这个依赖,可以使用如下仓库:

1
2
resolvers += "gliffy" at "http://maven.gliffy.com/content/repositories/public",
libraryDependencies += "com.hadoop.gplcompression" % "hadoop-lzo" % "0.4.16" % "provided"