Screaming Loud

日々是精進

scalaでssh処理(ssh, scpなど)

scalassh処理をしたい!ってなった時に、まず思いつくのは、sys.processだと思います。
sys.processを使えば、生のコマンドが実行できますので、自由にsshだったりなんだったりできます。

しかし、sprayやAkkaのコミッターである
sirthias (Mathias) · GitHub
が、ssh用のライブラリを作ってくれています。
sirthias/scala-ssh · GitHub


せっかくなので使ってみました。

ライブラリのインポート

まず、以下をインポートします。

libraryDependencies ++= Seq(
  "com.decodified" %% "scala-ssh" % "0.7.0" // メインのライブラリ
  "ch.qos.logback" % "logback-classic" % "1.1.2" //ログ用
  "org.bouncycastle" % "bcprov-jdk16" % "1.46", // 暗号化用
  "com.jcraft" % "jzlib" % "1.1.3" //圧縮用
)

実装

以下で実装している処理は、

  • パスワードによるssh接続
  • mkdirでリモート上でディレクトリを作成
  • scpで作成したディレクトリにファイルを送信

となっております。

このライブラリを使ってあげることで、SSH接続に関しては委譲することができ、なんのコマンドを発行するかに集中できました。

また、sshのログイン方法をパスワードにしていますが、
公開鍵方式でもアクセス可能です。

その際は、

HostConfig(PublicKeyLogin(user, password, keyLocation))

で設定してあげるとできるかと思います。

sbt-assembly

これで万事解決かと思いきや、
ssh-assemblyでjarに固める際に、インポートしたライブラリの"org.bouncycastle"が悪さをします。

具体的に言うと、ライブラリ内で競合が発生します。
scala - assembly-merge-strategy issues using sbt-assembly - Stack Overflow

そこで、sbt-assembly 0.11.2での解決方法は、以下をassembly.sbtかbuild.sbtに追加します。

mergeStrategy in assembly <<= (mergeStrategy in assembly) { (old) =>
  {
    // 競合した際に、先に出てきた方を使う
    case PathList("org", "bouncycastle", xs @ _*) => MergeStrategy.first 
    case x => old(x)
  }
}

sbt-assembly0.12では書き方が変わっていたので、ご注意ください。