initで呼び出された場合、^ Cをintr信号にbashマッピングできないのはなぜですか?

initで呼び出された場合、^ Cをintr信号にbashマッピングできないのはなぜですか?

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.c4501行の式にあります。

(t = tcgetpgrp (shell_tty)) == -1

エラー値は、ENOTTY呼び出しプロセスに制御端末がないことを示します。

initで呼び出すときにBashに制御端末がないのはなぜですか?

ベストアンサー1

これ制御端子bash準備(開封)されましたlogin。したがって、bashinitskiingを直接呼び出すと、login制御端末が信号処理に特別な役割を果たすため、上記の問題が発生します。

ソースコードによるとlogin.c(中util-linux)呼び出しプロセスbashはおおよそlogin次のとおりです。

  1. main() は fork_session() を呼び出します。

    /*
     * Detach the controlling terminal, fork, and create a new session
     * and reinitialize syslog stuff.
     */
    fork_session(&cxt);
    
  2. 新しいプロセスをフォークします。(fork_session()機能的に)

    child_pid = fork();
    
  3. 新しいプロセスをセッションリーダーにします。 端末制御を取得するには、まずプロセスがセッションリーダーになる必要があります。 (fork_session()機能的に)

    /* start new session */
    setsid();
    
  4. セッションリーダーの制御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"));
    
  5. 新しいプロセスでログインシェルを実行します。(返品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);
    

概念への追加リンク制御端子:

おすすめ記事