Java で ssh や scp を呼び出す(1)

ちょい仕事で JavaSSH/SCP を実行するライブラリがあるといいな的展開があって、ちょっと調べたら良さそうなのがあったので、メモ。

Ganymed SSH-2 for Java
http://www.ganymed.ethz.ch/ssh2/

最初読めなかったけど、「ガニメデ」ですね。

  • 100% Pure Java
  • SSH2 をサポート
  • コマンド実行、shell, scp, port forward 機能をサポート
  • BSD ライセンス

昔は Java から scp を叩ける良いライブラリがまだ無く、結局そのときは外部コマンド実行によって実現したものだが、今はこんないいものがあるんやね。


外部コマンド実行だと、どうしても

  • コマンドごとに認証(よってパフォーマンス悪し)
  • 若干不安定(よってエラー処理が面倒)
  • 標準入出力周りの処理をしっかりする必要がある(よってコーディング量が増える)
  • パスワード/パスフレーズが使えない(よってパスフレーズを空で鍵ペアを作らないといけない)

という何重苦なんだか、という状態に陥るのだが、 Ganymed ならずいぶん改善されそうである。


早速 scp のテストコードを組んでみた。
エラー処理は省いているとはいえ、こんなに短く書けるなんて、外部コマンド実行でのあの苦労は何だったんだー! と海に向かって叫びたいところである。

import java.io.IOException;
import ch.ethz.ssh2.*;

public class ScpTest {

	private static final String hostname = "ホスト名";
	private static final String userid   = "ユーザ名";
	private static final String password = "パスワード";

	public static void main(String[] arg) {
		try {
			ScpTest test = new ScpTest();
			test.doProc();
		} catch (IOException ex) {ex.printStackTrace();}
	}

	public void doProc() throws IOException {
		// connect & login
		Connection conn = new Connection(hostname);
		ConnectionInfo info = conn.connect();
		boolean result = conn.authenticateWithPassword(userid, password);

		if (result) {
			// "abc<CR><LF>"
			private byte[] b = {48, 49, 50, 13, 10};

			// scp
			SCPClient scp = conn.createSCPClient();
			scp.put(b, "testtest1.txt", "~/");
			scp.put(b, "testtest2.txt", "~/");
			scp.put(b, "testtest3.txt", "~/");
		}
		conn.close();
	}
}

連続での scp 転送も問題なし(実は1回目より2回目・3回目の方が実行時間がかかる。内部で呼び出している Connect.openSession() の2回目以降が遅いのか??)。


例外は全て IOException。
これは好みもあるだろうが、できれば独自に Exception クラスを定義して欲しかった。


コマンド実行時は都度 OpenSession() を呼ぶ必要があるが、また今度。