터미널을 절대 닫을 수 없다면 데몬이 제어 터미널에서 스스로 분리되는 이유는 무엇입니까?

터미널을 절대 닫을 수 없다면 데몬이 제어 터미널에서 스스로 분리되는 이유는 무엇입니까?

데몬 작성에 대해 내가 읽은 모든 내용에는 데몬이 제어 터미널에서 분리되어 터미널이 닫히면 데몬이 SIGHUP 신호를 수신하지 않도록 해야 한다고 나와 있습니다.

그러나 데몬 프로세스는 항상 init 프로세스에 의해 시작됩니다. htop이는 내 init 프로세스(systemd)에 제어 터미널이 없으므로 생성된 데몬에도 제어 터미널이 없음을 보여줍니다. SysVinit에서 어떻게 작동하는지 모르겠지만 변경 로그에 제어 터미널이 없거나 "/dev/console"을 사용한다는 힌트가 있습니다. 제가 틀렸을 수도 있지만 이는 항상 존재하고 종료할 수 없는 특수 커널 tty인 것 같습니다.

내가 뭐 놓친 거 없니?

나는 이것이 제어 터미널에서 분리하는 것보다 각 데몬에 대해 새로운 프로세스 세션을 시작하는 것에 관한 것이라고 생각합니다. 세션은 데몬이 하위 프로세스를 생성할 때 도움이 될 수 있습니다. 세션은 이러한 하위 프로세스를 추적합니다. 이를 통해 우리는 그들 모두를 죽일 수 있습니다.

답변1

@AndyDalton과 @muru가 지적했듯이(감사합니다!) SysVinit과 Systemd는 다르게 작동합니다.

systemd에서 데몬은 init 프로세스에 의해서만 생성됩니다. systemctl과 같은 데몬을 제어하는 ​​데 사용되는 cli-tools는 IPC를 통해 init 프로세스에 명령을 보낸 다음 작업을 수행합니다. 그들은 자체적으로 D-bus를 구현한 sd-bus를 사용합니다. D-bus 시스템 메시지 버스가 제대로 작동하지 않는 경우 소켓을 사용하여 대체할 수 있지만 이를 위해서는 루트 권한이 필요합니다. (실제로 다시 내려갈 수 있을지는 잘 모르겠습니다. 설명을 토대로 추측한 것입니다.이 경우그리고이 토론)

SysVinit에 관한 한 데몬에 신호를 보내고 데몬을 생성하는 것은 데몬 관련 bash 스크립트의 작업입니다. init 프로세스는 시작 시 이 스크립트를 실행합니다. 그러나 cli를 통해 수동으로 데몬을 시작하려면 이 스크립트를 직접 실행할 수 있습니다. 그러면 데몬은 bash 프로세스의 하위 프로세스가 되며 제어 터미널을 갖게 됩니다. 자세한 내용은 sysvinit 데몬 스크립트 예제와 인터넷의 "service" cli 도구를 참조하세요. "서비스"는 단지 bash 스크립트입니다. 데비안 패키지 "sysvinit-utils"에서 찾을 수 있습니다. init 프로세스는 실행 중인 데몬을 추적하기 위해 PID 파일만 사용하는 것 같습니다.

이것이 SysVinit 데몬이 제어 터미널에서 분리되어야 하는 이유입니다. 최신 데몬(systemd, upstart 등)에는 필요하지 않습니다. 이것은 또한 이 부분이 왜 나오는지 설명합니다.수동:

  1. 최신 데몬은 제어 TTY 없이(그러나 자체 세션 리더로) 호출되기 때문에 제어 TTY가 실수로 획득되지 않도록 TTY 장치 노드를 참조할 수 있는 호출을 항상 지정하도록 주의해야 합니다 O_NOCTTY.open()

결론적으로:

  1. Systemd는 SysVinit 스타일의 두 분기 데몬(type=forking)을 지원하지만 이는 데몬 작성에 권장되는 방법은 아닙니다.. 이중 포크가 필요하지 않습니다.

  2. systemd가 당신을 위해 setid()를 수행하는 것 같습니다:

   Note that new-style init systems guarantee execution of daemon
   processes in a clean process context: it is guaranteed that the
   environment block is sanitized, that the signal handlers and mask
   is reset and that no left-over file descriptors are passed.
   Daemons will be executed in their own session, with standard
   input connected to /dev/null and standard output/error connected
   to the systemd-journald.service(8) logging service, unless
   otherwise configured. The umask is reset

이는 데몬이 제어 터미널에서 분리될 필요가 없는 또 다른 이유입니다. 이미 새 세션에 참여하고 있습니다.

  1. 데몬은 해당 세션의 리더입니다. 따라서 데몬은 제어 터미널을 획득하지 않도록 제어 터미널을 열 때 주의해야 합니다.하지만 최신 운영 체제에서는 실수로 이 작업을 수행하는 것이 약간 어렵습니다.SIGHOP이 단지 구성을 다시 로드하라는 요청인 경우 제어 터미널을 가져오는 것은 그다지 큰 문제가 아닐 수 있습니다.

  2. 확실하진 않지만 그런 것 같아요systemd는 제어 그룹을 사용하여 데몬의 하위 프로세스를 추적하고 종료합니다.그렇다면 왜 setid가 필요한가요? 내 경우에는 지금 회의 중인지, 아니면 통제 그룹이 별도의 회의가 필요한지 - 잘 모르겠습니다. 어쩌면 세션이 이 목적으로 사용되지 않았을 수도 있습니다. 하지만 이제는 통제 그룹을 사용합니다.

고쳐 쓰다:

  1. @Uncle Billy는 터미널을 통해 프로세스로 보낼 수 있는 다른 신호를 언급했습니다. 나는 약간의 연구를했다.SIGINT, SIGQUIT 및 SIGSTP는 tty 라인 규칙에 의해 전송됩니다.이러한 신호는 termios의 c_lflag에 ISIG 플래그가 설정된 경우 전송됩니다. 와이어 규칙은 포그라운드 프로세스 그룹에 신호를 보냅니다. 포격할 정도는 아닙니다. 쉘은 포그라운드 프로세스 그룹의 pid를 라인 규칙에 미리 보고합니다. ISIG의 기본값을 찾을 수 없습니다. 그러나 포그라운드 프로세스 그룹이 수동으로 설정되지 않은 경우(즉, 우리 프로세스가 작업 인식 셸이 아닌 경우) 프로세스는 이러한 신호를 수신하지 못할 가능성이 높습니다. 어쩌면 이것은 터미널이 제어되는지 여부와 관련이 없을 수도 있습니다. 직업 통제에 관한 것입니다. 그러나 나는 틀릴 수 있습니다. Bourne 쉘과 같이 작동 방법을 모르는 쉘이 SIGINT를 어떻게 처리하는지 궁금합니다. "trap" 명령은 이에 대한 메커니즘이 다르다는 것을 나타냅니다.

관련 정보