Linux
關機時向正在執行的程序/腳本發送什麼信號?
現在我有以下內容:
# 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 上提出問題,而不是退出 shell。
我不想關閉機器,反正我不經常這樣做:
關機時向正在執行的程序/腳本發送什麼信號?
在關閉時,首先由 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 sources/init.c,這裡是圍繞 SIGTERM 輪的程式碼。如果向任何程序發送了 SIGTERM,請在 5 秒內每秒測試一次,以查看是否有任何程序剩餘。如果在其中一項測試中未找到任何程序,請等待,或在 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. */