reboot
Linux에서는 셸에서 명령을 실행하는 경우 bash
셸(예:)의 연결을 끊게 만드는 일련의 이벤트는 무엇입니까?
다음 중 하나인 것 같은데 어느 것인지는 확실하지 않습니다.
- 다시 시작 신호를 보내기 전에 쉘에서 로그아웃됩니다.
- 재시작 신호를 보낸 다음 쉘이 나를 로그아웃시킵니다.
- 재시작 신호를 보내고 로그아웃 프로세스를 수행하지 않고 쉘이 갑자기 종료됩니다.
답변1
이 동작은 배포/셸/구성에 따라 달라질 수 있습니다. 내 시스템(Gentoo/SysVinit)에서 재부팅을 실행하면 다음이 발생합니다(아마도 시나리오 3):
다시 시작 명령 위임 종료(에서 man reboot
):
시스템이 실행 레벨 0 또는 6이 아닐 때(즉, 시스템이 정상적으로 실행 중일 때) 정지 또는 재부팅이 호출되면 종료가 호출됩니다(-h 또는 -r 플래그 사용). 자세한 내용은 shutdown(8) 맨페이지를 참조하십시오.
모든 프로세스(셸 포함)는 SIGTERM을 수신하여 정리하는 데 3초가 소요됩니다( 에서 man shutdown
).
모든 프로세스는 먼저 SIGTERM 신호를 수신하여 시스템이 곧 종료될 것임을 알립니다. 이는 vi(1)와 같은 프로그램이 편집 중인 파일을 저장할 시간을 제공하고, 메일 및 뉴스 처리 프로그램이 완전히 종료될 수 있는 기회를 제공합니다.
-t sec는 init(8)에게 다른 실행 수준으로 변경하기 전에 모든 프로세스에 경고(SIGTERM)와 종료 신호(SIGKILL)를 보내는 사이에 초 동안 기다리도록 지시합니다. 값을 지정하지 않으면 두 신호 사이의 기본 시간은 3초입니다. 경고: shutdown이 init를 호출하여 종료(기본 동작)를 수행하면 init는 모든 프로세스가 종료되었는지 확인하고 하위 프로세스가 모두 종료되면 조기에 대기를 중지합니다. -n 플래그와 함께 shutdown을 호출하면 다른 모든 프로세스가 종료되더라도 지정된 전체 시간(또는 3초) 동안 기다립니다.
Bash는 실제로 SIGTERM(from man bash
)을 무시합니다.
bash가 대화형일 때 트랩 없이 SIGTERM을 무시합니다(따라서 Kill 0은 대화형 쉘을 종료하지 않습니다).
따라서 init
런레벨을 변경하고 (아마도) 다른 SIGTERM을 보낸 다음 SIGKILL을 보냅니다( 에서 man init
).
init가 런레벨을 변경하라는 요청을 받으면 새 런레벨에 정의되지 않은 모든 프로세스에 경고 신호 SIGTERM을 보냅니다. 그런 다음 3초 동안 기다린 후 SIGKILL 신호를 통해 이러한 프로세스를 강제 종료합니다.
너무 길면 bash가 정상적으로 종료되지 않고 종료되며 다른 프로그램도 종료될 수 있지만 특정 동작에 의존하지는 않습니다.
답변2
다른 사람들이 이미 지적했듯이 "Linux"가 무엇인지에 대한 복잡한 철학적 질문에 대한 귀하의 대답에 많은 것이 달려 있습니다. :)
예, 이 경우에는 다른 많은 경우와 마찬가지로 "GNU/Linux" 밈이 갑자기 매우 중요하고 관련성이 높아졌습니다.
이제 먼저 이 메커니즘이 실제로 어떻게 작동하는지에 대한 실제 "핵심 사실"을 살펴보겠습니다.
일반 커널에 관한 한 PID1이 실행되는 한 모든 것이 정상입니다. 그러나 PID1이 충돌하면 시스템의 하드웨어/소프트웨어가 아무리 건강하더라도 즉시 커널 패닉이 발생합니다. 이는 SIGKILL을 사용하여 모든 프로세스를 종료하는 것과 동일하거나 즉각적인 정전과 거의 동일한 효과를 갖습니다.
내가 올바르게 기억한다면 대부분의 기본 Linux는 기본적으로 여기에 갇혀 콘솔에 PANIC 메시지를 인쇄하고 운영자가 도착할 때까지 CPU가 정지할 때까지 기다린 후 머신을 물리적으로(또는 가상 머신인 경우 가상으로) 하드 리셋/종료합니다. ). 일부 BDS는 기본적으로 이 상태에서 15초를 기다린 후 자동으로 다시 시작됩니다.
그래서 그것은 일의 일부입니다.
다른 부분은 재부팅()이라는 특수 Linux 커널 시스템 호출입니다. 이 시스템 호출은 루트 프로세스에만 액세스할 수 있으며 커널 동작을 제어할 수 있습니다. 현재 커널에서 체인의 다음 커널로 kexec할 수 있고, 머신을 물리적으로 재부팅/재설정하고, 머신의 전원을 물리적으로 끄고, 머신을 물리적으로 중지하고, 마지막으로 머신을 일시 중지(최대 절전 모드)합니다.
최대 절전 모드(그것은 잘 모르겠습니다)를 제외하고 위에 언급된 모든 작업은 첫 번째 경우의 커널 패닉 작업과 동일합니다(즉, 실행 중인 모든 프로세스가 정전처럼 즉시 종료됩니다). kexec는 제어 체인의 다음 코어를 즉시 전환하는 반면, 다시 시작, 전원 끄기 및 일시 중지는 패닉을 일으키지 않고 모든 CPU를 다시 시작하거나 전체 시스템의 전원을 끄거나 모든 CPU를 중지한다는 것입니다 :).
일시 중지 상태는 기본적으로 모든 소프트웨어가 종료되는 상태로, 마더보드가 자동으로 전원을 차단하는 회로를 추가하기 전에 기존 컴퓨터를 종료하는 방법과 동일합니다("이제 컴퓨터를 안전하게 종료할 수 있습니다").
알아야 할 중요한 부분은 재부팅()이 시작될 때 PID1/init가 실행되어야 한다는 것입니다.
이제 이 두 가지 컨트롤이 정말 간단하다는 것을 알게 되었습니다. 또한 이제 특정 사용자 명령 shutdown과 restart() 시스템 호출 사이에서 발생하는 모든 작업은 완전히 배포판에 따라 다르다는 것을 이해했습니다.
이 시퀀스가 처리되는 방법은 일반적으로 배포판에서 사용되는 init 패키지에 따라 다릅니다. 대부분의 최신 배포판에서 이는 systemd에 의해 처리됩니다. PID1은 reboot
, poweroff
및 init 명령(이러한 명령은 다른 init와 작동하지 않으므로 실제로는 , 및 shutdown
로 이름을 지정해야 함 )에서 제어 명령을 받고 적절한 작업을 수행합니다.systemd-reboot
systemd-poweroff
systemd-shutdown
systemd 작성자 사이트 어딘가에서 종료 프로토콜이 어떻게 구현되는지 파헤칠 수 있습니다. 저는 이것을 읽은 것을 기억합니다(systemd는 지속적으로 변화하고 이에 대한 대부분의 심층 정보는 약 2012~15년 동안의 정보이므로 주의 깊게 이해하시기 바랍니다). 기간이며 실제로는 오래되었습니다).
이제 우리는 훨씬 더 기괴한 영역으로 들어가고 있습니다.
@rhellen은 형편없는 sysv init poweroff 댄스에 대한 간단한 설명을 제공했습니다.
runit
nosh
기반 배포판은 시스템 기반 배포판과 마찬가지로 완전히 다른 메커니즘을 가지고 있습니다 s6
.
따라서 실제 대답은 배포판에 따라 많이 달라진다는 것입니다.
예를 들어, 일부 고대 sysv 기반 Linux 시스템에서 reboot
명령 poweroff
은 원래 시스템 호출 대응물과 동일합니다(BSD에서도 마찬가지라고 생각합니다). 따라서 초보 관리자, 적어도 일반적인 시스템 사용자는 다음과 같은 강력한 능력을 갖습니다. 전체 상자를 "전원 끄기" 방식으로 종료합니다. :) Solaris의 경우와 비슷한 이야기입니다 killall
.
다행스럽게도 shutdown
거의 모든 플랫폼에서 항상 동일한 방식으로 작동하므로 의심스러운 경우 항상 해당 플랫폼을 사용하십시오.