nohup에도 불구하고 터미널을 닫으면 크롬 브라우저가 종료되는 이유는 무엇입니까?


12

이 질문은 오래되었지만 여전히 이유가 확실하지 않습니다.


2014 년 원문 :

그놈 터미널 탭에서

$ nohup chromium-browser &

그러나 터미널 탭을 닫으면 chromium-browser종료됩니다. 되지 않는 nohup것을 방지하기 위해 가정? 은 말했다 :

nohup과 disown은 SIGHUP을 억제한다고 할 수 있지만 다른 방식으로 말입니다. nohup은 프로그램이 처음에 신호를 무시하도록합니다 (프로그램이이를 변경할 수 있음). nohup은 또한 터미널을 닫을 때 커널이 SIGHUP을 보내지 않도록 제어 터미널이없는 프로그램을 구성하려고 시도합니다. disown은 순전히 쉘 내부에 있습니다. 쉘이 종료 될 때 SIGHUP을 보내지 않도록합니다.

그렇다면 nohup은 크롬 브라우저가 SIGHUP을 무시하지 않습니까?

Emacs (GUI 모드)와 같은 다른 실행 파일에서도 이것을 볼 수 있습니다. 그러나 xeyes에는 없습니다.

이것은 질문이 게시 된 32 비트 Ubuntu 12.04에서 발생합니다.


2015 년 업데이트

이제 설치 google-chrome대신 Ubuntu 14.04를 실행 중 chromium-browser입니다. 크롬 크롬 브라우저에서 일어난 것과 같은 일이 이제 구글 크롬에서도 발생합니다. nohup google-chrome 2>/dev/null &터미널 탭을 닫을 때 닫히는 것을 저장하지 않습니다. /usr/bin/google-chromebash 스크립트에 대한 링크 /opt/google/chrome/google-chrome입니다. 왜 nohupbash 스크립트에 적용되지 않습니까? bash 스크립트에서 어떻게 작동하게 할 수 있습니까? 파이썬 스크립트는 어떻습니까?


1
당신은 당신의 환경에 대해 더 많이 말해야합니다. 테스트 사례를 재현하지 않습니다.
jlliagre

어떤 다른 실행 파일이 있습니까? 예를 들어 다음과 같은 간단한 것을 시도하십시오 xeyes.
Warren Young

@WarrenYoung : 이맥스 (GUI). 그러나 xeyes는 작동합니다.
Tim

답변:


12

그놈 터미널 창을 닫으면 SIGHUP이 실행중인 쉘로 전송됩니다. 쉘은 일반적으로 SIGHUP을 자신이 생성 한 것으로 알고있는 모든 프로세스 그룹에 전송 한 nohup다음 종료합니다. 쉘이있는 경우, bash사용자가 표시된 프로세스 그룹으로 SIGHUP 전송을 건너 뜁니다 disown.

로 명령을 실행하면 nohupSIGHUP을 무시하지만 프로세스가이를 변경할 수 있습니다. 프로세스의 SIGHUP 처리가 기본값 인 경우 SIGHUP을 수신하면 프로세스가 종료됩니다.

Linux는 실행중인 프로세스의 신호 설정을 검사 할 수있는 도구를 제공합니다.

크롬 브라우저 셸 스크립트는 exec컴파일 된 앱을 수행하므로 프로세스 ID는 동일하게 유지됩니다. 신호 설정 을 확인하기 위해 신호 처리 nohup chromium-browser &를 보았습니다 /proc/$!/status.

SigBlk: 0000000000000000
SigIgn: 0000000000001000
SigCgt: 0000000180014003

그것들은 16 진수입니다. 이것은 SIGHUP이 포착되지 않고 무시되지 않음을 나타냅니다. SIGPIPE (SigIgn의 13 번째 비트) 만 무시됩니다. 나는 이것을 다음 코드로 추적했다 .

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

주석에도 불구하고 부모가 무시한 신호는 무시 되지 않습니다 . SIGHUP은 크롬을 죽입니다.

해결 방법은 @ xx4h가 지적한 것을 수행하는 것입니다. disownbash 에서 명령을 사용하여 bash를 종료해야 SIGHUP을 chromium-browser프로세스 그룹으로 보내지 않도록하십시오 . 이를 수행하는 함수를 작성할 수 있습니다.

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

감사. 이제 나는 당신이 무엇을 의미하는지 대부분 이해하게되었습니다. "스크립트가이 트랩을 재설정하지 않기 때문에 실제 크롬 바이너리는 SIGHUP의 배치가 기본값으로 설정되어 호출됩니다." "이 트랩 재설정"은 SIGHUP의 트랩을 기본 트랩으로 다시 변경하여 프로세스를 종료한다는 의미입니까? "이 함정을 어떻게 재설정합니까?"
Tim

"트랩 재설정"이라는 의미는 "쉘 스크립트가 처리기를 설정하기 전의 상태로이 신호의 배치를 다시 설정하는 것"을 의미했습니다. 만약 쉘이 그렇게한다면, 쉘 trap "" 1과 그 자식들은 SIGHUP을 무시하게됩니다. 나는 이것을 명확히 할 것이다.
Mark Plotnick

감사. 설명 후 확인하겠습니다. 나는 지금 데몬, nohup, disown 및 배경을 이해하려고 노력하고 있으므로, 내가 이해하지 못했던 이전 질문과 답을 다시 방문했습니다. nohup, disown 및 background에 대한 혼란은 대부분 해결되었으며 데몬의 개념과 프로세스를 데몬 화하는 방법에 붙어 있습니다 (아래 참조). 다시 도와 드릴 시간이 있으면 다시 한번 감사드립니다.
Tim


크롬 앱 코드를 살펴본 결과 응용 프로그램의 C ++ 코드가 SIGHUP을 무조건 기본값으로 재설정합니다. trap쉘 스크립트 랩퍼 의 명령으로이를 방지 nohup할 수 없으며 실행으로 이를 방지 할 수 없습니다. 이를 반영하여 답변을 수정하겠습니다.
Mark Plotnick

3

경우 chromium-browser처럼 아무거나 google-chrome다음은 내가 가장 가능성있는 문제는 그 생각 chromium-browser 하지 않습니다chromium 하지만 상태를 초기화 쉘 - 래퍼 대신 인 execchromium.

google-chrome설치에서 바이너리는 실제로 위치하고 /opt/google/chrome래퍼는 기본 및 절대 경로와 /usr/bin관련하여 많은 환경을 설정 xdg-*하고 바이너리 자체로 바꾸기 전에 비슷한 쉘 스크립트 일뿐 입니다.

이 시점에서 nohup자식으로 호출 된 스크립트를 대신하여 처음에 무시했을 수 있는 신호 는 문제 가 사라지고 래퍼 스크립트가 그렇지 않으면 ctty가 상속 되지 않도록 정렬하도록주의하지 않으면 신호가 중단됩니다 .

시도 file /usr/bin/chromium-browser는 내가 생각하는 쉘 스크립트인지 확인합니다. 그렇다면 더 잘 맞도록 다시 작성해보십시오.

나는 그렇게 google-chrome 2>/dev/null &하는 것이 나를 위해 계속 열려 있다고 말할 수는 있지만, 그것이 내가 스크립트를 수정 한 결과 일 수 있는지는 기억할 수 없습니다 .1 년 전이었습니다.


감사. chromium-browser전에 일어난 일도 google-chrome지금도 일어납니다 . chromium-browser설치 하지 않았습니다 . nohup google-chrome 2>/dev/null &터미널 탭을 닫을 때 닫히는 것을 저장하지 않습니다. google-chromebash 스크립트 /opt/google/chrome/google-chrome입니다. bash 스크립트에 적용된 nohup이 작동하지 않는 이유는 무엇입니까? bash 스크립트에서 어떻게 작동하게 할 수 있습니까? 파이썬 스크립트는 어떻습니까?
Tim

음, 하지 스크립트 작업을하지만, 스크립트는 실제로 대체되기 전에 몇 나노 초 동안 실행 chrome바이너리.
mikeserv

스크립트에서 실제 바이너리 exec에 있다고 말하고 chrome있습니까? 그러면 스크립트를 어떻게 수정합니까? 여기는 내/opt/google/chrome/google-chrome

@Tim-예-하단을 보시겠습니까? exec -a "$0" "$HERE/chrome" ... || exec -a "$0" "$HERE/chrome"... 맨 위에는 (설치 경로 )$HERE 의 값으로 설정되어 있지만 바이너리는 스크립트 자체로 대체되는 바이너리입니다. readlink $0 google-chrome/opt/google/chrome/chrome
mikeserv

@Tim : 어떻게되는지 - exec아마 떨어 뜨릴 수 있습니다 . 여분의 pid (1000 개 이외) 와 대기 쉘 프로세스가 있지만, 그 정도라고 생각합니다. 아니면 당신은 대체 할 수 exec승 / nohup어쩌면. 그것은 모두 무엇 chrome을 견딜 것인가에 달려 있지만, 그렇게 작동해야합니다.
mikeserv

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.