Perché il browser al cromo viene ucciso quando chiudo il terminale nonostante nohup?


12

Questa domanda è vecchia e non sono ancora chiaro il perché.


Domanda originale nel 2014:

In una scheda Terminale di Gnome, ho corso

$ nohup chromium-browser &

Ma quando chiudo la scheda del terminale, chromium-browseresce anche. Non nohupdovrebbe impedirlo? Gilles disse:

si può dire che nohup e disconoscimento sopprimono SIGHUP, ma in modi diversi. nohup fa inizialmente ignorare il segnale al programma (il programma potrebbe cambiarlo). nohup cerca anche di far sì che il programma non abbia un terminale di controllo, in modo che non venga inviato SIGHUP dal kernel quando il terminale è chiuso. la disconnessione è puramente interna alla conchiglia; fa sì che la shell non invii SIGHUP quando termina.

Quindi nohup non fa ignorare SIGHUP al browser Chrome?

Lo vedo anche su altri eseguibili, come ad esempio e Emacs (modalità GUI). Ma non su xeyes.

Questo accade su Ubuntu 12.04, a 32 bit quando è stata posta la domanda.


Aggiornamento nel 2015,

Ora sto eseguendo Ubuntu 14.04, con google-chromeinvece di chromium-browserinstallato. La stessa cosa che è successa al browser Chromium prima succede anche a Google Chrome ora. nohup google-chrome 2>/dev/null &non lo salva dalla chiusura quando la scheda del terminale è chiusa. /usr/bin/google-chromeè un collegamento a uno script bash /opt/google/chrome/google-chrome. Perché nohupapplicato allo script bash non funziona? Come possiamo farlo funzionare su script bash? Che dire degli script Python?


1
Dovresti dire di più sul tuo ambiente. Non riproduco il tuo caso di prova.
jlliagre,

Con quali altri eseguibili vedi questo? Prova qualcosa di semplice, ad esempio, come xeyes.
Warren Young,

@WarrenYoung: Emacs (GUI). Ma xeyes funziona.
Tim

Risposte:


12

Quando chiudi una finestra del Terminale GNOME, un SIGHUP viene inviato alla shell che era in esecuzione. La shell in genere invia un SIGHUP a tutti i gruppi di processi che sa di aver creato - anche quelli iniziati con nohup- e quindi esce. Se la shell lo è bash, salterà l'invio di un SIGHUP a qualsiasi gruppo di processi contrassegnato dall'utente disown.

L'esecuzione di un comando con nohupfa ignorare SIGHUP, ma il processo può cambiarlo. Quando la disposizione di SIGHUP per un processo è l'impostazione predefinita, quindi se riceve un SIGHUP, il processo verrà terminato.

Linux fornisce alcuni strumenti per esaminare le impostazioni del segnale di un processo in esecuzione.

Lo script della shell del browser chromium esegue execun'app compilata, quindi l'ID del processo rimane lo stesso. Quindi, per vedere le sue impostazioni del segnale, ho corso nohup chromium-browser &e poi ho guardato /proc/$!/statusper vedere la disposizione del segnale.

SigBlk: 0000000000000000
SigIgn: 0000000000001000
SigCgt: 0000000180014003

Questi sono numeri esadecimali. Questo dimostra che SIGHUP non viene rilevato e non ignorato. Solo SIGPIPE (il 13 ° bit in SigIgn) viene ignorato. Ho rintracciato questo al seguente codice :

// 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);
}

Nonostante il commento, i segnali ignorati dal genitore non vengono ignorati. Un SIGHUP ucciderà il cromo.

La soluzione è fare ciò che @ xx4h sottolinea: utilizzare il disowncomando in bash in modo che, se bash deve uscire, non invii SIGHUP al chromium-browsergruppo di processi. È possibile scrivere una funzione per fare ciò:

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

Grazie. Ora capisco soprattutto cosa intendevi. "Poiché lo script non reimposta mai questa trappola, l'attuale binario al cromo viene chiamato con la disposizione di SIGHUP impostata sul valore predefinito." Con "resetta questa trappola", intendi ripristinare la trappola di SIGHUP con quella predefinita, che termina il processo? Come si "resetta questa trappola"?
Tim

Oh, "resettando questa trappola", intendevo "riporta la disposizione di questo segnale al modo in cui era prima che lo script della shell ne impostasse un gestore". Se lo avesse fatto trap "" 1, ciò avrebbe fatto sì che lo shell (e i suoi figli) ignorassero SIGHUP. Chiarirò questo.
Mark Plotnick

Grazie. Lo controllerà dopo il tuo chiarimento. Ora sto cercando di capire demone, nohup, disconoscimento e background, quindi sono tornato per rivisitare le mie vecchie domande e le risposte che non avevo capito. Le confusioni su nohup, disown e background sono per lo più risolte, e sono bloccato con il concetto di demone e come demonizzare un processo (vedi sotto). Apprezzo di nuovo se hai tempo per aiutare di nuovo.
Tim


Ho esaminato il codice dell'app chromium e risulta che il codice C ++ nell'applicazione reimposta incondizionatamente SIGHUP. I trapcomandi nel wrapper dello script della shell non lo impediscono e l'esecuzione nohupnon può impedirlo. Revisionerò la mia risposta per riflettere questo.
Mark Plotnick

3

Se chromium-browserè qualcosa del genere, google-chromepenso che il problema più probabile sia che chromium-browser non lo sia,chromium ma è invece un involucro della shell che inizializza lo stato, quindi execs chromium.

Nella mia google-chromeinstallazione il binario si trova in realtà /opt/google/chromee il wrapper in /usr/binè solo uno script di shell che imposta un sacco di ambiente riguardante xdg-*impostazioni predefinite e percorsi assoluti e simili prima di sostituirsi con il proprio binario.

A questo punto qualsiasi segnale che nohupinizialmente avrebbe potuto essere ignorato per conto dello script chiamato come suo figlio cesserà di avere importanza e, a meno che lo script wrapper non stia attento a disporlo altrimenti (cosa che non lo è), il ctty viene ereditato.

Prova file /usr/bin/chromium-browsera controllare se è lo script di shell penso che sia. In tal caso, considera di riscriverlo per adattarlo meglio a te.

Posso dire che il solo fatto lo google-chrome 2>/dev/null &tiene aperto per me, ma non ricordo se questo è probabilmente il risultato di modifiche che ho apportato alla sceneggiatura: è successo più di un anno fa.


Grazie. La stessa cosa che è successa chromium-browserprima succede anche google-chromeadesso. Non ho chromium-browserinstallato. nohup google-chrome 2>/dev/null &non lo salva dalla chiusura quando la scheda del terminale è chiusa. google-chromeè uno script bash /opt/google/chrome/google-chrome. Perché nohup applicato a uno script bash non funziona? Come possiamo farlo funzionare su script bash? Che dire degli script Python?
Tim

Beh, fa il lavoro sulla sceneggiatura, ma lo script viene eseguito solo per pochi nano-secondi prima di essere sostituito dal reale chromebinario.
Mikeserv,

stai dicendo nella sceneggiatura che c'è execdavvero sul chromebinario? Come posso quindi modificare lo script? Ecco il mio/opt/google/chrome/google-chrome
Tim

@ Tim - sì - vedi il fondo? exec -a "$0" "$HERE/chrome" ... || exec -a "$0" "$HERE/chrome"... Nella parte superiore $HEREè impostato il valore di readlink $0 (che è il percorso di installazione per google-chrome) ma /opt/google/chrome/chromeè il binario - che è quello con cui lo script si sostituisce.
Mikeserv,

@Tim: per quanto va - puoi semplicemente rilasciare il execprobabilmente. Finirai con un pid extra (oltre i suoi altri 1000) e un processo di shell in attesa, ma penso che sia l'estensione. Altrimenti potresti sostituire execw / nohupforse. Tutto dipende principalmente da ciò chromeche tollererà, ma dovrebbe funzionare così.
Mikeserv,

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.