bash를 첫 번째 호출 프로세스(즉, init)로 설정하면 결과적으로 다음이 표시됩니다.
init: cannot set terminal process group (-1): Inappropriate ioctl for device
init: no job control in this shell
그리고 어떤 신호(예: ^C, ^Z)도 작동하지 않습니다.
bash-5.1.12의 소스 코드를 읽으면 문제는 job.c
4501행의 표현식에 있습니다.
(t = tcgetpgrp (shell_tty)) == -1
오류 값은 ENOTTY
호출 프로세스에 제어 터미널이 없음을 나타내는 입니다.
init로 호출할 때 Bash에 제어 터미널이 없는 이유는 무엇입니까?
답변1
이것제어 터미널bash
준비(개봉) 되었습니다 login
. 따라서 bash
initskiing을 직접 호출 하면 login
제어 터미널이 신호 처리에 특별한 역할을 하기 때문에 위의 문제가 발생합니다.
소스코드에 따르면login.c(중간 util-linux
) 호출 프로세스 bash
는 대략 login
다음과 같습니다.
main()은 fork_session()을 호출합니다.
/* * Detach the controlling terminal, fork, and create a new session * and reinitialize syslog stuff. */ fork_session(&cxt);
새로운 프로세스를 포크합니다.(
fork_session()
기능적으로)child_pid = fork();
새 프로세스를 세션 리더로 만듭니다. 터미널 제어권을 얻으려면 먼저 프로세스가 세션 리더가 되어야 합니다. (
fork_session()
기능적으로)/* start new session */ setsid();
세션 리더의 제어 tty를 가져옵니다.
open
세션 리더는 tty를 통해 제어 터미널을 얻습니다. (fork_session()
기능적으로)/* make sure we have a controlling tty */ open_tty(cxt->tty_path); openlog("login", LOG_ODELAY, LOG_AUTHPRIV); /* reopen */ /* * TIOCSCTTY: steal tty from other process group. */ if (ioctl(0, TIOCSCTTY, 1)) syslog(LOG_ERR, _("TIOCSCTTY failed: %m"));
새 프로세스에서 로그인 셸을 실행합니다.(반품
main()
)/* if the shell field has a space: treat it like a shell script */ if (strchr(pwd->pw_shell, ' ')) { char *buff; xasprintf(&buff, "exec %s", pwd->pw_shell); child_argv[child_argc++] = "/bin/sh"; child_argv[child_argc++] = "-sh"; child_argv[child_argc++] = "-c"; child_argv[child_argc++] = buff; } else { char tbuf[PATH_MAX + 2], *p; tbuf[0] = '-'; xstrncpy(tbuf + 1, ((p = strrchr(pwd->pw_shell, '/')) ? p + 1 : pwd->pw_shell), sizeof(tbuf) - 1); child_argv[child_argc++] = pwd->pw_shell; child_argv[child_argc++] = xstrdup(tbuf); } child_argv[child_argc++] = NULL; /* http://www.linux-pam.org/Linux-PAM-html/adg-interface-by-app-expected.html#adg-pam_end */ (void) pam_end(cxt.pamh, PAM_SUCCESS|PAM_DATA_SILENT); execvp(child_argv[0], child_argv + 1);
개념에 대한 추가 링크제어 터미널: