コミュニティが実行するいくつかのサーバー用に Java で簡単なサービス マネージャーを作成しようとしています。一般的な考え方は、サーバー側アプリケーションがサーバーを起動し、Process クラスを介してそのコンソールのストリームにフックし、RDP を介して、またはリモートでユーザー セッションで実行できるクライアント アプリケーションに中継するというものです。
これで、ネットワーキングとリレーが正常に機能するようになりました。そのようなことは比較的簡単です。私が抱えている問題は、サーバー (またはタスクのみ) の再起動時にサーバーを安全にシャットダウンすることです。
ランタイムのシャットダウン フックがこれを処理する適切な方法であるという印象を受けましたが、機能していないようです。
私のコンソール ラッパー クラスの完全なコード: http://pastebin.com/vM3PQ9zE
これは、わかりやすくするためにクラス フィールドを追加してサービスを開始するメソッドです。
private final ProcessBuilder builder;
private Process process;
private boolean stopped = false;
private HashSet<ConsoleListener> listeners;
private PrintStream commandStream;
private InputHandler handler;
private Thread shutdownTask;
public void start() throws IOException {
if (this.hasStarted())
throw new IllegalStateException(
"This process has already been started once.");
this.process = this.builder.start();
for (ConsoleListener l : this.listeners) {
l.onStart(new ConsoleEvent(this));
}
this.handler = new InputHandler(this.process.getInputStream());
new Thread(this.handler).start();
this.commandStream = new PrintStream(this.process.getOutputStream());
Runtime.getRuntime().addShutdownHook(
this.shutdownTask = new Thread(new ShutdownListener()));
}
クラス ShutdownListener は、次のようにインラインで定義されています。
private class ShutdownListener implements Runnable {
@Override
public void run() {
ConsoleApplication.this.nuke();
}
}
nuke メソッドは次のように定義されます。
public void nuke() {
this.process.destroy();
}
最終的には、ラッパーが安全なシャットダウンのために適切なコマンドを送信できるようにしたいと考えていますが、プロセスを強制的に閉じることさえできないようです。シャットダウン フックを動かしてみましたが、テストの結果、nuke() が呼び出されていないことがわかりました。
どんな助けでも大歓迎です。
ノート:
私はタスク スケジューラに接続していません。サーバーの起動時に処理する最も簡単な方法のようです。タスク スケジューラを使用しない解決策があれば、ぜひお聞かせください。