
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)を送信するまでの間待機するように指示します。値を指定しない場合、2つの信号間のデフォルト時間は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を実行する必要があることです。
これで、これら2つのコントロールが本当に簡単であることがわかりました。また、特定のユーザーコマンド 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
ほぼすべてのプラットフォームで常に同じ方法で動作するため、疑わしい場合は常にそのプラットフォームを使用してください。