Linux: プロセス管理 — ps / top / killとシステム監視

Linuxでは、実行中のプログラムをプロセスと呼びます。プロセスの管理 — 何が動いているか、リソースをどれだけ使っているか、どう安全に停止するか — はサーバー管理のコアスキルです。

📋 前提条件:まず以下を完了していること

1. このレッスンで学ぶこと


2. サービスが起動しないストーリー

(1) 悩み:ポートが既に使用中

小明はNode.jsサービスを起動しようとして次のエラーに遭遇しました:

BASH
node server.js
# Error: listen EADDRINUSE: address already in use :::3000

ポートが占有されていました。どのプロセスがポート3000を使っているのか、どう停止すればいいのか分かりませんでした。

(2) ポートを特定して解放

BASH
# Find the process using port 3000
ss -tlnp | grep 3000
# LISTEN 0 128 *:3000 *:* users:(("node",pid=1234,fd=20))

# Terminate the process
kill 1234

# Restart the service
node server.js

(3) 得られるもの:ポート競合の解決

小明はsslsofでポートを占有するプロセスを見つけ、killでシグナルを送って終了する方法を学びました。今では30秒でポート競合を解決できます。


3. 知識ポイント

(1) ps — プロセススナップショット

BASH
# Core usage
ps aux               # Detailed info on all processes
ps aux | grep nginx  # Filter specific processes
ps -ef               # Standard format

# Common field meanings
# USER    PID  %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
# alice  1234  0.3  1.2 123456 54321 ?        Ssl  10:23   0:01 node server.js

# Custom output
ps -eo pid,user,%cpu,%mem,comm --sort=-%cpu | head -10
フィールド 意味
PID プロセスID
PPID 親プロセスID
%CPU CPU使用率
%MEM メモリ使用率
VSZ 仮想メモリサイズ(KB)
RSS 物理メモリサイズ(KB)
STAT プロセス状態(R=実行中、S=待機、D=割り込み不可、Z=ゾンビ、T=停止)
START 開始時刻
TIME 累積CPU時間
COMMAND コマンド名 / コマンドライン

(2) top/htop — リアルタイム監視

TEXT
top                             # Start top
top -o %MEM                     # Sort by memory
top -u alice                    # Show only specific user processes
top -bn1 | head -20             # One-shot output

# Hotkeys while top is running
# P    Sort by CPU
# M    Sort by memory
# k    Kill process (prompts for PID)
# u    Filter by user
# q    Quit top

# htop is an enhanced version of top (nicer UI, mouse support)
htop

(3) kill — シグナルの送信

BASH
kill PID                        # Send SIGTERM (15), request termination
kill -2 PID                     # Send SIGINT (2), equivalent to Ctrl+C
kill -9 PID                     # Send SIGKILL (9), force termination
kill -1 PID                     # Send SIGHUP (1), reload config
kill -19 PID                    # Send SIGSTOP (19), pause process
kill -18 PID                    # Send SIGCONT (18), resume process

# Kill by name
pkill -f "node server.js"       # Match command line
killall nginx                   # Kill all processes with the same name
シグナル 番号 意味
SIGHUP 1 ハングアップ(設定再読み込み)
SIGINT 2 割り込み(Ctrl+C)
SIGQUIT 3 終了(コアダンプ付き)
SIGKILL 9 強制終了(捕捉/無視不可)
SIGTERM 15 終了要求(デフォルト)
SIGSTOP 19 停止(捕捉/無視不可)
SIGCONT 18 実行再開

核心原則: まずkill PID(SIGTERM)を試す。それでも終了しない場合のみkill -9 PID(SIGKILL)を使用。SIGKILLはプロセスにクリーンアップの機会を与えず、データ損失の原因になる可能性があります。

⚠️ 警告kill -9(SIGKILL)はプロセスを強制終了し、クリーンアップの機会がありません — 開いているファイルが破損、データベーストランザクションが中断、一時ファイルが残留する可能性があります。kill PID(SIGTERM)が応答しない場合のみ-9を使用してください。ショートカットとして使わないこと。

(4) バックグラウンド実行

TEXT
# & — Put in background
node server.js &                 # Returns terminal immediately after starting

> 💡 ヒント:コマンドの末尾に`&`を付けるとバックグラウンドで実行され、ターミナルがすぐに解放されます。ただし、`&`だけではターミナルセッション終了時にプロセスも終了します。ターミナルを閉じてもプロセスを継続させるには、`nohup`と組み合わせます:`nohup command &`。
sleep 30 &                       # Run sleep in background

# jobs/fg/bg — Manage background jobs
jobs                            # List background jobs
# [1]+  Running                 node server.js &
# [2]-  Running                 sleep 30 &
fg %1                          # Bring job 1 to foreground
bg %2                          # Resume paused job 2 in background

# Ctrl+Z — Suspend current foreground job and put in background
# Ctrl+C — Terminate foreground job

# nohup — Keep running after terminal closes
nohup node server.js &
nohup python app.py > app.log 2>&1 &

> ℹ️ 注意:`nohup` + `&`が永続的バックグラウンドコマンドの標準組み合わせ — `nohup`はSIGHUPシグナル(ターミナル終了時に送信)を無視し、`&`はバックグラウンド実行。出力はデフォルトで`nohup.out`に書き込まれます。ログファイルを手動指定することを推奨:`nohup command > app.log 2>&1 &`。

(5) ▶ サンプル:プロセスの確認

BASH
# View all processes
ps aux | head -10

# View processes for a specific user
ps -u alice -o pid,%cpu,%mem,comm

# Top 10 processes by CPU usage
ps aux --sort=-%cpu | head -11

# View process tree
ps auxf | head -20

出力:

TEXT
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.0  0.1 169344 13224 ?        Ss   10:00   0:02 /sbin/init
root         2  0.0  0.0      0     0 ?        S    10:00   0:00 [kthreadd]
alice     1234  0.3  1.2 123456 54321 ?        Ssl  10:23   0:01 node server.js
alice     2345  0.0  0.0   2345   567 pts/0    S+   10:30   0:00 ps aux
PID   USER     %CPU  %MEM  COMMAND
1234  alice    0.3   1.2   node
5678  bob      0.1   0.5   python3
USER   PID %CPU %MEM  COMMAND
root   1   0.0  0.1   /sbin/init
root   456 0.5  2.1   /usr/bin/containerd
alice  1234 8.2  3.4   node server.js
bob    2345 5.1  4.2   python train.py

(6) ▶ サンプル:リアルタイム監視

TEXT
# Start top
top

# Operations inside top
# P → Sort by CPU
# M → Sort by memory
# k → Enter PID, press Enter, enter signal number (15 or 9), press Enter
# q → Quit

# Non-interactive mode
top -bn1 | head -15

出力:

TEXT
top - 10:30:01 up  5:23,  2 users,  load average: 0.15, 0.10, 0.05
Tasks: 120 total,   1 running, 119 sleeping,   0 stopped,   0 zombie
%Cpu(s):  2.3 us,  0.8 sy,  0.0 ni, 96.5 id,  0.2 wa,  0.0 hi,  0.2 si
MiB Mem :   3936.0 total,    512.0 free,   2048.0 used,   1376.0 buff/cache

(7) ▶ サンプル:プロセスの終了

BASH
# Start a background process
sleep 1000 &

# Find it
ps aux | grep "sleep 1000"
# alice  5678  0.0  0.0   1234   567 pts/0    S    10:23   0:00 sleep 1000

# Graceful termination
kill 5678

# If that doesn't work
kill -9 5678

出力:

TEXT
[1]+  Terminated              sleep 1000
alice  5678  0.0  0.0   1234   567 pts/0    S    10:23   0:00 sleep 1000
[1]+  Killed                  sleep 1000

(8) ▶ サンプル:バックグラウンド実行の実践

BASH
# Start a long-running task
nohup python train_model.py > train.log 2>&1 &

# View the log
tail -f train.log

# Even after closing the terminal, train_model.py continues running
# After re-logging in, ps aux will show it's still running

出力:

TEXT
[1] 5678
[2026-07-07 10:23:01] Training epoch 1/100...
[2026-07-07 10:23:15] Loss: 0.5234
[2026-07-07 10:23:30] Training epoch 2/100...

(9) ▶ サンプル:nice/renice優先度調整

TEXT
# nice range: -20 (highest priority) to 19 (lowest priority)

# Start with lower priority
nice -n 10 ./heavy-task

# Adjust priority of an existing process
renice -n 5 -p 1234

# View process nice values
ps -eo pid,nice,comm | head -10

(10) ▶ 総合例:サービス管理

BASH
#!/bin/bash
# manage-server.sh - Manage a Node.js application

APP_NAME="server.js"
APP_DIR="/home/alice/app"
PID_FILE="/tmp/app.pid"

start() {
    if [ -f "$PID_FILE" ] && kill -0 $(cat "$PID_FILE") 2>/dev/null; then
        echo "App is already running (PID: $(cat $PID_FILE))"
        exit 1
    fi
    cd "$APP_DIR"
    nohup node "$APP_NAME" > app.log 2>&1 &
    echo $! > "$PID_FILE"
    echo "App started (PID: $!)"
}

stop() {
    if [ ! -f "$PID_FILE" ]; then
        echo "App is not running"
        exit 1
    fi
    PID=$(cat "$PID_FILE")
    echo "Stopping app (PID: $PID)..."
    kill "$PID" 2>/dev/null
    sleep 2
    if kill -0 "$PID" 2>/dev/null; then
        echo "Force killing..."
        kill -9 "$PID" 2>/dev/null
    fi
    rm -f "$PID_FILE"
    echo "Stopped"
}

status() {
    if [ -f "$PID_FILE" ] && kill -0 $(cat "$PID_FILE") 2>/dev/null; then
        echo "Running (PID: $(cat $PID_FILE))"
        ps -p $(cat "$PID_FILE") -o pid,%cpu,%mem,etime,comm
    else
        echo "Not running"
    fi
}

case "${1:-status}" in
    start) start ;;
    stop) stop ;;
    restart) stop; start ;;
    *) status ;;
esac

❓ よくある質問

Q: なぜkill -9は安全ではないのですか? A: kill -9(SIGKILL)はプロセスをクリーンアップなしで即座に強制終了します — 開いているファイルが破損、データベーストランザクションが中断、一時ファイルが残留する可能性があります。kill PID(SIGTERM)が応答しない場合のみ使用してください。

Q: ゾンビプロセスとは何ですか? A: 終了したが親プロセスが終了ステータスを読み取っていないプロセスです。プロセステーブルに「ゾンビ」エントリが残ります(STAT=Z)。ゾンビ自体はリソースを消費しませんが、多すぎるとプロセステーブルが枯渇します。通常、親プロセスをkillまたは再起動してクリーンアップします。

Q: nohupとdisownの違いは? A: nohupは起動時にSIGHUPを無視するようプロセスを設定します(ターミナル終了時に送信)。disownはbash組み込みで、既に起動したジョブをシェルのジョブテーブルから削除します。nohup command &が最も一般的なアプローチ。

Q: プロセスのCPU使用率を制限するには? A: cpulimitを使用:cpulimit -l 50 -p PIDで50%に制限。またはniceで優先度を下げる。Dockerコンテナでは--cpusで制限。

Q: 特定ポートを使用しているプロセスを見つけるには? A: ss -tlnp | grep :PORT(推奨)、lsof -i :PORT(lsofが必要)、またはfuser PORT/tcp


📖 まとめ


📝 練習問題

  1. 基本(難易度 ⭐)ps aux --sort=-%cpuでCPU使用率上位3プロセスを見つけ、sleep 300 &を起動し、jobsで確認し、killで終了する
  2. 中級(難易度 ⭐⭐)nohupで長時間実行コマンドを起動し、ターミナルを閉じ、再度開いてプロセスがまだ動いていることを確認する。次にss -tlnpで全リスニングポートと関連プロセスを確認する
  3. 上級(難易度 ⭐⭐⭐):start/stop/status/restartコマンドをサポートするプロセス管理スクリプトを作成 — PIDファイルでプロセスを追跡し、graceful終了(SIGTERM、3秒待機、その後SIGKILL)を実装
Web-Tutorial.com

Web-Tutorial 技術チーム

複数の開発者によって共同維持されているプログラミングチュートリアルプラットフォーム。各チュートリアルは専門分野の開発者が執筆・レビューしています。正確で信頼性の高いコンテンツを目指しています — 問題を見つけた場合はお知らせください。

100%