
【基礎から学び直すITインフラ入門】#10 Linux基礎③ - プロセスとシグナル
この記事では、Linuxのプロセスとシグナルについて解説します。
このあたりからインフラ屋ではない私にとって、若干あやふやな部分がでてきそう。。。前回記事は ↓ から
はじめに
前回は、Linuxのディレクトリ構造とパスの概念について学びました。ディレクトリの階層構造や、絶対パスと相対パスの違いを理解できたと思います。
今回は、プロセスとシグナルについて学びます。Linuxではこのプロセスをどのように管理し、制御しているのか、 また、シグナルとは何かを理解することで、サーバーで動いているプログラムを適切に管理できるようになります。
プロセスとは
プロセスは、プログラムが実際にメモリ上で実行されている状態のことです。プログラムが起動されると、プロセスが生まれます。
※プログラムは、ディスク上に保存されている実行可能なファイルで、例えば、Webサーバーソフトウェアのnginxなどが該当します。
プロセスID(PID)
Linuxでは、起動した各プロセスにプロセスID(PID) という一意の番号が割り振られます。この番号を使って、プロセスを識別したり、操作したりします。
PIDは1から順番に割り振られ、システムが起動して最初に実行されるプロセスのPIDは常に1です(通常はsystemdやinitというプロセスが割り当てられます)。
親プロセスと子プロセス
Linuxでは、あるプロセスが別のプロセスを起動することができます。このとき、起動した側を親プロセス、起動された側を子プロセスと呼びます。
この親子関係を辿っていくと、最終的には全てのプロセスがPID 1のプロセス(通常はsystemd)に行き着きます。つまり、Linuxのプロセスは木構造(ツリー構造) になっています。この親子関係の全体像をプロセスツリーと呼びます。
# プロセスツリー
systemd (PID: 1)
├─ sshd (PID: 500)
│ └─ sshd (PID: 1234)
│ └─ bash (PID: 1235)
│ └─ vim (PID: 1300)
├─ nginx (PID: 600)
│ ├─ nginx worker (PID: 601)
│ └─ nginx worker (PID: 602)
└─ mysqld (PID: 700)親プロセスが終了すると、通常は子プロセスも終了します。ただし、親が死んでも子プロセスが生き残る場合もあり、その場合は孤児プロセスとなってPID 1に引き取られます。
プロセスの確認
ps - プロセスの一覧表示
現在動いているプロセスを確認するには、psコマンドを使います。
# 全ユーザーのプロセスを詳細表示
ps aux
# 出力例:
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.1 168548 12000 ? Ss 10:00 0:01 /sbin/init
root 500 0.0 0.0 72304 3200 ? Ss 10:00 0:00 /usr/sbin/sshd
hiro 1235 0.0 0.1 21460 5000 pts/0 Ss 10:30 0:00 -bash
hiro 1300 0.5 0.2 25800 8000 pts/0 S+ 11:00 0:10 vim memo.txt
# オプション解説:
# a 他ユーザーの実行プロセスも含める
# u 詳細表示
# x 端末に依存しないプロセスも含める
# つまり、このマシン上で動いている全プロセスとなる。主な列の意味:
USER: プロセスを実行しているユーザー
PID: プロセスID
%CPU: CPU使用率
%MEM: メモリ使用率
COMMAND: 実行しているコマンド
STAT: プロセスの状態(後述)
top / htop - リアルタイム監視
psは実行した瞬間の断面ですが、topやhtopはリアルタイムでプロセスの状態を監視できます。
top - 11:30:00 up 1 day, 2:30, 1 user, load average: 0.00, 0.01, 0.05
Tasks: 150 total, 1 running, 149 sleeping, 0 stopped, 0 zombie
%Cpu(s): 0.3 us, 0.2 sy, 0.0 ni, 99.5 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st
MiB Mem : 3934.0 total, 2500.0 free, 800.0 used, 634.0 buff/cache
MiB Swap: 2048.0 total, 2048.0 free, 0.0 used. 2900.0 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
1300 hiro 20 0 25800 8000 2000 S 0.3 0.2 0:10.50 vim
1 root 20 0 168548 12000 8000 S 0.0 0.3 0:01.00 systemd
500 root 20 0 72304 3200 2500 S 0.0 0.1 0:00.20 sshdプロセスの状態
プロセスには、いくつかの状態があります。psコマンドのSTAT列や、topのS列に表示されます。
主な状態:
R (Running): 実行中、またはCPUを待っている状態
S (Sleeping): 何かのイベント(入力待ちなど)を待っている状態。ほとんどのプロセスはこの状態です。
D (Uninterruptible Sleep): 割り込み不可能なスリープ状態。通常はディスクI/O待ちです。
T (Stopped): 一時停止状態
Z (Zombie): ゾンビプロセス。すでに終了しているが、親プロセスがまだ終了を確認していない状態
プロセスとスレッドの違い
プロセスと似た概念にスレッドがあります。
プロセスは、独立したメモリ空間を持つ実行単位です。各プロセスは互いに干渉せず、独立して動作します。
スレッドは、プロセス内の実行単位です。1つのプロセスが複数のスレッドを持つことができ、同じメモリ空間を共有します。
プロセスは重いが独立性が高く、スレッドは軽いが干渉のリスクがあるため、実行する処理によって使い分ける必要があります。
シグナル
シグナルは、プロセスに対して送る通知や指示のことです。プロセスを終了させたり、一時停止させたり、設定を再読み込みさせたりするために使います。Linuxには様々な種類のシグナルがあり、それぞれ異なる意味を持っています。
主要なシグナル
SIGTERM (15): 終了要求
プロセスに終了してくださいを指示するシグナルです。プロセスは、このシグナルを受け取ると、開いているファイルを閉じたり、接続を切断したりといった後片付けをしてから終了します。
SIGKILL (9): 強制終了
プロセスを問答無用で強制終了させるシグナルです。プロセスはこのシグナルを無視できず、即座に終了します。後片付けは一切行われません。
※ SIGTERMで終了しないプロセスに対して、最後の手段としてSIGKILLを使います。
SIGHUP (1): ハングアップ
元々は端末との接続が切れたことを通知するシグナルでしたが、現在では「設定ファイルを再読み込みしてください」という意味で使われることが多いです。
例えば、nginxの設定ファイルを変更した後、SIGHUPを送ることで、サーバーを再起動せずに設定を反映できます。
SIGINT (2): 割り込み
プロセスを中断させるシグナルで、Ctrl+Cを押したときに送られます。
SIGSTOP (19) / SIGCONT (18): 一時停止と再開
SIGSTOPでプロセスを一時停止し、SIGCONTで再開します。
killコマンド - シグナルの送信
プロセスにシグナルを送るには、killコマンドを使います。
また、プロセス名を使ってシグナルを送ることもできます。
# プロセスID 1300 に SIGTERM を送る(デフォルト)
kill 1300
# 明示的にSIGTERMを指定
kill -15 1300
# または
kill -TERM 1300
# SIGKILLで強制終了
kill -9 1300
# または
kill -KILL 1300
# SIGHUPを送って設定再読み込み
kill -HUP 1300
# または
kill -1 1300
# プロセス名を指定して実行
pgrep nginx # PIDを確認
pkill nginx※名前に反して、killコマンドは必ずしも殺すわけではなく、様々なシグナルを送るための汎用コマンドです。
バックグラウンド実行
フォアグラウンドとバックグラウンド
通常、コマンドを実行すると、そのコマンドが終了するまでターミナルが占有されます。これをフォアグラウンド実行と呼びます。
一方、コマンドをバックグラウンドで実行すると、ターミナルを占有せず、他のコマンドを実行できます。
# フォアグラウンドで実行(ターミナルが占有される)
sleep 100
# バックグラウンドで実行(すぐにプロンプトが返る)
sleep 100 &&を付けると、そのコマンドはバックグラウンドで実行されます。
jobs - バックグラウンドジョブの確認
# バックグラウンドジョブの一覧表示
jobs
# 出力例:
[1]+ Running sleep 100 &
[2]- Running find / -name "*.log" &fg / bg - フォアグラウンド/バックグラウンドの切り替え
# 実行中のプロセスを一時停止(Ctrl+Z)
# (例: vimを編集中)
^Z
[1]+ Stopped vim memo.txt
# バックグラウンドで再開
bg
# フォアグラウンドに戻す
fgnohup - ログアウト後も実行を継続
通常、ターミナルからログアウトすると、そこで起動したプロセスは全て終了します。しかし、nohupコマンドを使うと、ログアウト後もプロセスを継続できます。
# ログアウト後も実行を継続
nohup ./long_running_script.sh &
# 出力は nohup.out に保存されるこれは、時間のかかる処理をサーバーで実行する際に使われます。
まとめ
今回は、Linuxのプロセスとシグナルについて学びました。
プロセスの確認(ps / top)や、killコマンドによるシグナル送信は、実務でも頻繁に使用される基本操作です。本記事を通して、それぞれのコマンドや仕組みの意味を整理できたのではないでしょうか。
また、プロセスの状態や、フォアグラウンド・バックグラウンド、ジョブ制御などを理解することで、サーバー上で動作するプログラムの扱い方がよりイメージしやすくなったと思います。
個人的にも、業務上使っていたわけですが、言語化することで曖昧になっていたそれぞれの知識が整理できた気がしてよいですね。
ここまでで、Linuxの基本的な仕組み(ディレクトリ・プロセス)を一通り押さえました。
次回は、Linuxの根幹であるファイルシステムについて解説します。ファイルやディレクトリがどのように管理されているのかを理解し、より実践的な操作につなげていきます。