Pregunta

Me gustaría para determinar el estado de salida del proceso durante el tiempo de ejecución del gancho de cierre.

Quiero tener una lógica que se basa en el código de estado (0 ó distinto de cero)

(por ejemplo: si es cero hacer otra cosa distinta de cero, envíe un correo electrónico de alerta)

¿Sabe usted cómo puedo obtener esta información?

¿Fue útil?

Solución

He intentado reemplazar el método SecurityManager checkExit(int status) - esto funciona si System.exit(status) se llama explícitamente en cualquier lugar - sin embargo, no establece el estado cuando se cierra la aplicación "normalmente" (sin hilos activos), o mata a un error de la máquina virtual.

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.security.Permission;


public class ExitChecker {

    public ExitChecker() {

        System.setSecurityManager(new ExitMonitorSecurityManager());

        Runtime.getRuntime().addShutdownHook(new Thread(new MyShutdownHook()));

        BufferedReader input = new BufferedReader(new InputStreamReader(System.in));
        String line = "";
        while (!line.equalsIgnoreCase("Q")) {
            try {
                System.out.println("Press a number to exit with that status.");
                System.out.println("Press 'R' to generate a RuntimeException.");
                System.out.println("Press 'O' to generate an OutOfMemoryError.");
                System.out.println("Press 'Q' to exit normally.");
                line = input.readLine().trim();

                processInput(line);
            } catch (IOException e) {
                e.printStackTrace();
                System.exit(-1);
            }
        }
    }

    private void processInput(String line) {
        if (line.equalsIgnoreCase("Q")) {
            // continue, will exit loop and exit normally
        } else if (line.equalsIgnoreCase("R")) {
            throwRuntimeException();
        } else if (line.equals("O")) {
            throwError();
        } else {
            // try to parse to number
            try {
                int status = Integer.parseInt(line);
                callExit(status);
            } catch(NumberFormatException x) {
                // not a number.. repeat question...
                System.out.println("\nUnrecognized input...\n\n");
            }
        }
    }

    public void callExit(int status) {
        System.exit(status);
    }

    public void throwError() {
        throw new OutOfMemoryError("OutOfMemoryError");
    }

    public void throwRuntimeException() {
        throw new RuntimeException("Runtime Exception");
    }

    public static void main(String[] args) {
        new ExitChecker();
    }

    private static class ExitMonitorSecurityManager extends SecurityManager {

        @Override
        public void checkPermission(Permission perm) {
            //System.out.println(perm.getName());
            //System.out.println(perm.getActions());
        }

        @Override
        public void checkPermission(Permission perm, Object context) {
            //System.out.println(perm.getName());
            //System.out.println(perm.getActions());
        }

        @Override
        public void checkExit(int status) {
            System.out.println("Setting exit value via security manager...");
            MyShutdownHook.EXIT_STATUS = status;
        }
    }

    private static class MyShutdownHook implements Runnable {

        public static Integer EXIT_STATUS;

        public void run() {

            System.out.println("In MyShutdownHook - exit status is " + EXIT_STATUS);
        }
    }

}

Otros consejos

Aquí hay un código ejemplo, mediante el cual se utiliza una clase dedicada a iniciar una llamada System.exit través de una llamada a doExit(int). La clase también almacena el estado de salida y posteriormente actúa como un gancho de cierre hacia abajo.

public class ShutDownHook implements Runnable {
  private volatile Integer exitStatus;

  // Centralise all System.exit code under control of this class.
  public void doExit(int exitStatus) {
    this.exitStatus = exitStatus;
    System.exit(exitStatus); // Will invoke run.
  }

  public void run() {
    // Verify that an exit status has been supplied.
    // (Application could have called System.exit(int) directly.)
    if (this.exitStatus != null) {
      switch(exitStatus) {
        case 0: // Process based on exit status.
        // Yada yada ...
      }
    }
  }
}

¿Por qué hacer esto en la aplicación itsellf? Si la aplicación no está enviando a correos electrónicos como parte de las operaciones normales, la incorporación de este tipo de funcionalidad no es una buena idea, en mi humilde opinión.

Me acaba de confiar a establecer un valor de retorno adecuado en el proceso de JVM y dejar un script de shell o lo que se encargan de la creación condicional de la dirección de correo.

Shutdownhooks se supone que deben funcionar sólo por un corto tiempo, el envío de un correo electrónico podría consumir bastante tiempo.

Debe guardar el estado de salida en main en una variable global (public static).

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top