Wake on LAN してみる Part 3 (shutdown)
前回までで、とりあえず リモートで PC を起動できるようにはなったのだが...
今更ながら気づく。リモートで起動できるのに リモートでは停止できないことに...
これでは 必要な時だけサーバを起動しておくという当初の目的が達成できない。
もちろん、リモートログインすれば PC を停止できる。
でも、PC を停止するためだけに 毎回 リモートログインして
shutdown コマンドを実行するのも面倒...
特に Windows は SSH クライアントが標準装備されていないし...
と言うことで...
今回は リモートで Linux サーバを停止するための処理を JavaFX で実装してみた。
ちなみに 今回 対象とする Linux ディストリビューションは Ubuntu だけ...
他のディストリビューションでも停止できるかどうかは不明。
JavaFX で ネットワーク上の Linux サーバを停止するのもそれほど難しくはない。
要は自分自身が行っている
- Linux サーバにリモートログインする。
- root 権限で shutdown コマンドを実行する。
当然 リモートログインは SSH で行います。
もちろん Telnet でもできますが 今時 Telnet でログインできるサーバなんてありえない...
と言うことで、
JavaFX で SSH してみることに...
残念ながら Java の標準APIは SSH をサポートしていないので
別途ライブラリが必要になる。
SSH 用のライブラリはいくつかあるようだが
今回は 一番メジャーと思われる JSch を使うことにした。
まず、jsch-x.y.z.jar をダウンロードして クラスパスに追加しておく。
後は 以下のように実装するだけ...
例のごとく 例外処理等は全く考慮していません。
import java.io.ByteArrayInputStream; import java.lang.*; import com.jcraft.jsch.ChannelExec; import com.jcraft.jsch.JSch; // サーバ情報 def host = "192.168.1.1"; def port = 22; // ユーザ情報 def username = "hoge"; def password = "pass"; // shutdown コマンド def command = "sudo -S -p '' /sbin/shutdown -h now"; def jsch = new JSch(); def session = jsch.getSession(username, host, port); try { // SchException: UnknownHostKey を防ぐための設定 session.setConfig("StrictHostKeyChecking", "no"); session.setPassword(password); session.connect(5000); var channel = session.openChannel("exec") as ChannelExec; try { channel.setCommand(command); channel.setInputStream(new ByteArrayInputStream("{password}\n".getBytes())); channel.setOutputStream(System.out); channel.setErrStream(System.err); channel.connect(); // コマンドが終了するまで待機 while (not channel.isClosed()) { Thread.sleep(1000); } } finally { channel.disconnect(); } } finally { session.disconnect(); }
JSch の使い方は Examples を参照すれば大体わかるはず...
今回の実装は
echo "pass" | ssh hoge@192.168.1.1 "sudo -S -p '' /sbin/shutdown -h now"のように ssh コマンドを実行しているのとほぼ同じです。
ちなみに、上記のコマンドは リモートサーバ上で sudo して root 権限で shutdown コマンドを実行しています。
通常 sudo コマンドを実行するとパスワードを要求してきますが、"-S" オプションを付けることで
標準入力からパスワードを渡すことができるので、
『echo "pass"』で出力したパスワードをパイプ ( | ) で渡しているのです。
で、プログラムでは このパスワードの渡し方を
channel.setInputStream(new ByteArrayInputStream("{password}\n".getBytes()));で実現しています。
パスワードの最後に改行コードを付けるのを忘れないように注意しましょう。
この辺りの話は 『sudo をプログラムで使う際の注意点』 にまとめてありますのでよかったらどうぞ...
以上のように JavaFX で SSH を利用するのは とても簡単です。
SSH には この他にも まだまだ いろいろな使い道がありそうですね。
サーバを操作したり、サーバの情報を参照したりする ちょっとしたクライアントツールが簡単にできちゃいます。
今回のサンプルも まだ画面がないので はっきり言えば JavaFX で実装する意味はほとんどないですが...
一応、コマンドラインから
javafxc -classpath jsch-x.y.z.jar Main.fx javafx -classpath .:jsch-x.y.z.jar Mainと入力すれば実行できます。興味のある方は ぜひ試してみてください。