¿Por qué se mata el navegador de cromo cuando cierro el terminal a pesar de nohup?


12

Esta pregunta es antigua, y todavía no tengo claro por qué.


Pregunta original en 2014:

En una pestaña Terminal de Gnome, corrí

$ nohup chromium-browser &

Pero cuando cierro la pestaña del terminal, chromium-browsertambién sale. ¿No se nohupsupone que debe evitar eso? Gilles dijo:

Nohup y Disown pueden decirse que suprimen SIGHUP, pero de diferentes maneras. nohup hace que el programa ignore la señal inicialmente (el programa puede cambiar esto). nohup también trata de hacer arreglos para que el programa no tenga un terminal de control, de modo que el núcleo no lo envíe SIGHUP cuando el terminal esté cerrado. disown es puramente interno al caparazón; hace que el shell no envíe SIGHUP cuando termina.

Entonces, ¿no hace que el navegador de cromo ignore SIGHUP?

También estoy viendo esto en otros ejecutables, como Emacs (modo GUI). Pero no en xeyes.

Esto está sucediendo en Ubuntu 12.04, 32 bits cuando se publicó la pregunta.


Actualización en 2015,

Ahora estoy ejecutando Ubuntu 14.04, en google-chromelugar de chromium-browserinstalado. Lo mismo que le sucedió a chromium-browser antes también le sucede a google-chrome ahora. nohup google-chrome 2>/dev/null &no evita que se cierre cuando la pestaña del terminal está cerrada. /usr/bin/google-chromees un enlace a un script bash /opt/google/chrome/google-chrome. ¿Por qué no se nohupaplica aplicado al script bash? ¿Cómo podemos hacer que funcione en scripts de bash? ¿Qué pasa con los scripts de Python?


1
Debería contar más sobre su entorno. No reproduzco tu caso de prueba.
jlliagre

¿Con qué otros ejecutables estás viendo esto? Pruebe algo simple, por ejemplo, como xeyes.
Warren Young

@WarrenYoung: Emacs (GUI). Pero xeyes funciona.
Tim

Respuestas:


12

Cuando cierra una ventana de Terminal de GNOME, se envía un SIGHUP al shell que estaba ejecutando. El shell generalmente enviará un SIGHUP a cada grupo de procesos que sabe que creó, incluso los que comenzaron nohup, y luego se cerrará. Si el shell es bash, omitirá el envío de un SIGHUP a cualquier grupo de procesos con el que el usuario marcó disown.

Ejecutar un comando con nohuphace que ignore SIGHUP, pero el proceso puede cambiar eso. Cuando la disposición de SIGHUP para un proceso es la predeterminada, si recibe un SIGHUP, el proceso finalizará.

Linux proporciona algunas herramientas para examinar la configuración de la señal de un proceso en ejecución.

El script de shell de chromium-browser realiza una execde las aplicaciones compiladas, por lo que su ID de proceso sigue siendo la misma. Entonces, para ver la configuración de la señal, corrí nohup chromium-browser &y luego miré /proc/$!/statuspara ver la disposición de la señal.

SigBlk: 0000000000000000
SigIgn: 0000000000001000
SigCgt: 0000000180014003

Esos son números hexadecimales. Esto muestra que SIGHUP no se captura y no se ignora. Solo SIGPIPE (el 13er bit en SigIgn) se ignora. Rastreé esto hasta el siguiente código :

// Setup signal-handling state: resanitize most signals, ignore SIGPIPE.
void SetupSignalHandlers() {
  // Sanitise our signal handling state. Signals that were ignored by our
  // parent will also be ignored by us. We also inherit our parent's sigmask.
  sigset_t empty_signal_set;
  CHECK(0 == sigemptyset(&empty_signal_set));
  CHECK(0 == sigprocmask(SIG_SETMASK, &empty_signal_set, NULL));

  struct sigaction sigact;
  memset(&sigact, 0, sizeof(sigact));
  sigact.sa_handler = SIG_DFL;
  static const int signals_to_reset[] =
      {SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGABRT, SIGFPE, SIGSEGV,
       SIGALRM, SIGTERM, SIGCHLD, SIGBUS, SIGTRAP};  // SIGPIPE is set below.
  for (unsigned i = 0; i < arraysize(signals_to_reset); i++) {
    CHECK(0 == sigaction(signals_to_reset[i], &sigact, NULL));
  }

  // Always ignore SIGPIPE.  We check the return value of write().
  CHECK(signal(SIGPIPE, SIG_IGN) != SIG_ERR);
}

A pesar del comentario, las señales ignoradas por el padre no se ignoran. Un VISTAZO matará el cromo.

La solución es hacer lo que @ xx4h señala: use el disowncomando en su bash para que, si bash tiene que salir, no envíe SIGHUP al chromium-browsergrupo de procesos. Puede escribir una función para hacer esto:

mychromium () { /usr/bin/chromium-browser & disown $!; }

Gracias. Ahora llego a entender principalmente lo que querías decir. "Dado que el script nunca restablece esta trampa, el binario de cromo real se llama con la disposición de SIGHUP establecida por defecto". Con "restablecer esta trampa", ¿quiere decir que la trampa para SIGHUP vuelva a la predeterminada, que finaliza el proceso? ¿Cómo se "restablece esta trampa"?
Tim

Oh, al decir "restablecer esta trampa", me refería a "volver a poner la disposición de esta señal como estaba antes de que el script de shell estableciera un controlador para ella". Si el shell lo hiciera trap "" 1, eso haría que el shell (y sus hijos) ignoraran SIGHUP. Aclararé esto.
Mark Plotnick

Gracias. Lo comprobará después de su aclaración. Ahora estoy tratando de entender demonio, nohup, repudio y antecedentes, así que volví a revisar mis viejas preguntas y respuestas que no entendí. Las confusiones sobre nohup, disown y background están en su mayoría resueltas, y estoy atascado con el concepto de demonio y cómo demonizar un proceso (ver más abajo). Te agradezco nuevamente si tienes tiempo para ayudar de nuevo.
Tim


Miré el código de la aplicación de cromo, y resulta que el código C ++ en la aplicación restablece SIGHUP al valor predeterminado incondicionalmente. Los trapcomandos en el contenedor de script de shell no impiden esto, y la ejecución nohupno puede evitarlo. Revisaré mi respuesta para reflejar esto.
Mark Plotnick

3

Si chromium-browserse parece a algo así google-chrome, creo que el problema más probable es que chromium-browser no lochromium es, sino que es un envoltorio que inicializa el estado y luego execs chromium.

En mi google-chromeinstalación, el binario se encuentra en realidad /opt/google/chromey el contenedor /usr/bines solo un script de shell que establece una gran cantidad de entornos relacionados con los xdg-*valores predeterminados y las rutas absolutas y similares antes de reemplazarse con el binario propiamente dicho.

En este punto, cualquier señal que nohuppodría haber ignorado inicialmente en nombre del script que llamó como su hijo dejará de importar y, a menos que el script de contenedor tenga cuidado de organizarlo de otra manera (lo que no es), el ctty se hereda.

Intenta file /usr/bin/chromium-browsercomprobar si es el shell-script que creo que es. Si es así, considere reescribirlo para que se adapte mejor a usted.

Puedo decir que solo hacerlo lo google-chrome 2>/dev/null &mantiene abierto para mí, pero no puedo recordar si ese es un resultado probable de las modificaciones que hice al guión: fue hace más de un año.


Gracias. Lo mismo que sucedió chromium-browserantes también sucede google-chromeahora. No tengo chromium-browserinstalado nohup google-chrome 2>/dev/null &no evita que se cierre cuando la pestaña del terminal está cerrada. google-chromees un script bash /opt/google/chrome/google-chrome. ¿Por qué nohup aplicado a un script bash no funciona? ¿Cómo podemos hacer que funcione en scripts de bash? ¿Qué pasa con los scripts de Python?
Tim

Bueno, hace trabajar en el guión, pero el guión sólo funciona durante unos pocos nanosegundos antes de ser reemplazado por el actual chromebinario.
mikeserv

¿Estás diciendo en el guión que hay execen el chromebinario actual ? ¿Cómo modifico el script entonces? Aquí está mi/opt/google/chrome/google-chrome
Tim

@Tim, sí, ¿ves el fondo? exec -a "$0" "$HERE/chrome" ... || exec -a "$0" "$HERE/chrome"... En la parte superior $HEREse establece el valor de readlink $0 (que es su ruta de instalación google-chrome) pero /opt/google/chrome/chromees el binario, que es con lo que se reemplaza el script.
mikeserv

@Tim: En cuanto a cómo va, simplemente puede soltar el execprobablemente. Terminará con un pid extra (más allá de sus otros 1000) y un proceso de shell de espera, pero creo que ese es el alcance de esto. O bien, puede reemplazar execcon nohuptal vez. Todo depende principalmente de lo chromeque tolerará, pero debería funcionar así.
mikeserv

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.