종료 시 실행 중인 프로그램/스크립트에 어떤 신호가 전송됩니까?

종료 시 실행 중인 프로그램/스크립트에 어떤 신호가 전송됩니까?

이제 다음이 있습니다.

# this function is meant for future script expansions
# its purpose is clear, i.e. to clean up some temp files
# now, it is doing nothing, just a special null command
cleanup_on_signal() { :; }

# define functions to handle signals
# treat them as errors with appropriate messages
# example calls:
#    kill -15   this_script_name    # POSIX, all shells compatible
#    kill -TERM this_script_name    # Bash and alike - newer shells
signal_handler_HUP()   {  cleanup_on_signal; print_error_and_exit "\\ntrap()" "Caught SIGHUP (1).\\n\\tClean-up finished.\\n\\tTerminating. Bye!";    }
signal_handler_INT()   {  cleanup_on_signal; print_error_and_exit "\\ntrap()" "Caught SIGINT (2).\\n\\tClean-up finished.\\n\\tTerminating. Bye!";    }
signal_handler_QUIT()  {  cleanup_on_signal; print_error_and_exit "\\ntrap()" "Caught SIGQUIT (3).\\n\\tClean-up finished.\\n\\tTerminating. Bye!";   }
signal_handler_ABRT()  {  cleanup_on_signal; print_error_and_exit "\\ntrap()" "Caught SIGABRT (6).\\n\\tClean-up finished.\\n\\tTerminating. Bye!";   }
signal_handler_TERM()  {  cleanup_on_signal; print_error_and_exit "\\ntrap()" "Caught SIGTERM (15).\\n\\tClean-up finished.\\n\\tTerminating. Bye!";  }

# use the above functions as signal handlers;
# note that the SIG* constants are undefined in POSIX,
# and numbers are to be used for the signals instead
trap 'signal_handler_HUP' 1; trap 'signal_handler_INT' 2; trap 'signal_handler_QUIT' 3; trap 'signal_handler_ABRT' 6; trap 'signal_handler_TERM' 15

종료 시 스크립트가 깔끔하게 종료되기를 원했는데 지금은 그렇습니다.

하지만 동료의 조언을 받아들여 쉘로 나가는 대신 CTRL+C로 질문을 했습니다.

나는 기계를 종료하고 싶지 않습니다. 어쨌든 그렇게 자주 하지 않습니다.

종료 시 실행 중인 프로그램/스크립트에 어떤 신호가 전송됩니까?

답변1

종료 시 실행 중인 프로세스는 먼저 init(@JdeBP에 따라 이전 구현의 sendigs에서)/systemd에 의해 중지하라는 지시를 받습니다.

나머지 프로세스(있는 경우)에는 SIGTERM이 전송됩니다. SIGTERM을 무시하거나 제 시간에 완료되지 않는 프로세스는 곧 init/systemd에 의해 SIGKILL로 전송됩니다.

이러한 조치는 (최대한) 안정적이고 깨끗한 종료를 보장하기 위한 것입니다.

호기심에서 systemd관련 (이전) 버그 보고서를 참조하십시오.

버그 1352264 - systemd는 종료 중 SIGTERM 직후에 SIGKILL을 보냅니다.

systemd는 종료 중 SIGTERM 직후에 SIGKILL을 보내며 프로세스는 종료될 기회가 없습니다.

또한 shutdown.c/main()에서:

    disable_coredumps();

    log_info("Sending SIGTERM to remaining processes...");
    broadcast_signal(SIGTERM, true, true, arg_timeout);

    log_info("Sending SIGKILL to remaining processes...");
    broadcast_signal(SIGKILL, true, false, arg_timeout);

또한 sysvinit 2.94 source/init.c에서 SIGTERM 휠을 둘러싼 코드입니다. 프로세스가 SIGTERM으로 전송되면 프로세스가 남아 있는지 확인하기 위해 5초 동안 1초마다 테스트됩니다. 테스트 중 하나에서 프로세스가 발견되지 않으면 대기를 중지하거나 5초 후에 나머지 프로세스에 SIGKILL을 보냅니다.

        switch(round) { 
                case 0: /* Send TERM signal */
                        if (talk)
                                initlog(L_CO,
                                        "Sending processes configured via /etc/inittab the TERM signal");
                        kill(-(ch->pid), SIGTERM);
                        foundOne = 1;
                        break;
                case 1: /* Send KILL signal and collect status */
                        if (talk)
                                initlog(L_CO,
                                        "Sending processes configured via /etc/inittab the KILL signal");
                        kill(-(ch->pid), SIGKILL);
                        break;
        }
        talk = 0;

    }
    /*
     *  See if we have to wait 5 seconds
     */
    if (foundOne && round == 0) {
        /*
         *      Yup, but check every second if we still have children.
         */
        for(f = 0; f < sleep_time; f++) {
                for(ch = family; ch; ch = ch->next) {
                        if (!(ch->flags & KILLME)) continue;
                        if ((ch->flags & RUNNING) && !(ch->flags & ZOMBIE))
                                break;
                }
                if (ch == NULL) {
                        /*
                         *      No running children, skip SIGKILL
                         */
                        round = 1;
                        foundOne = 0; /* Skip the sleep below. */
                        break;
                }
                do_sleep(1);
        }
    }
  }

  /*
   *    Now give all processes the chance to die and collect exit statuses.
   */
  if (foundOne) do_sleep(1)
  for(ch = family; ch; ch = ch->next)
        if (ch->flags & KILLME) {
                if (!(ch->flags & ZOMBIE))
                    initlog(L_CO, "Pid %d [id %s] seems to hang", ch->pid,
                                ch->id);
                else {
                    INITDBG(L_VB, "Updating utmp for pid %d [id %s]",
                                ch->pid, ch->id);
                    ch->flags &= ~RUNNING;
                    if (ch->process[0] != '+')
                        write_utmp_wtmp("", ch->id, ch->pid, DEAD_PROCESS, NULL);
                }
        }

  /*
   *    Both rounds done; clean up the list.
   */

관련 정보