メインコンテンツまでスキップ

Linux 基礎

Linuxの基本概念、ディストリビューション、シェルの基礎を学びます。


目次

  1. Linuxとは
  2. ディストリビューション
  3. シェルの基礎
  4. 環境変数
  5. 標準入出力
  6. 仮想メモリ
  7. 基本的なコマンド操作
  8. ヘルプの使い方
  9. コンテナとの関係

Linuxとは

概要

Linuxは、Unix系のオープンソースオペレーティングシステムです。

┌─────────────────────────────────────────────────────────────┐
│ Linux システム構成 │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ アプリケーション │ │
│ │ (Web サーバー、データベース、etc.) │ │
│ └─────────────────────────────────────────────────────┘ │
│ │ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ シェル / ユーザー空間 │ │
│ │ (bash, システムライブラリ, ツール) │ │
│ └─────────────────────────────────────────────────────┘ │
│ │ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Linux カーネル │ │
│ │ (プロセス管理、メモリ管理、ファイルシステム、 │ │
│ │ ネットワーク、デバイスドライバ) │ │
│ └─────────────────────────────────────────────────────┘ │
│ │ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ ハードウェア │ │
│ │ (CPU、メモリ、ディスク、NIC) │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘

カーネルとは

カーネル(kernel)は、OSの中核部分です。

「kernel」は英語で「核」「芯」を意味します。ハードウェアとアプリケーションの間に位置し、コンピュータのすべてのリソースを管理します。

┌─────────────────────────────────────────────────────────────┐
│ カーネルの役割 │
├─────────────────────────────────────────────────────────────┤
│ │
│ アプリケーション │
│ (nginx, postgres, vim, ls, grep...) │
│ │ │
│ │ 「ファイルを読みたい」「メモリがほしい」 │
│ │ 「ネットワークに送りたい」 │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ システムコール │ │
│ │ (アプリケーションとカーネルの接点) │ │
│ │ open(), read(), write(), fork(), ... │ │
│ └─────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ カーネル │ │
│ │ │ │
│ │ ┌──────────────┐ ┌──────────────┐ │ │
│ │ │ プロセス管理 │ │ メモリ管理 │ │ │
│ │ └──────────────┘ └──────────────┘ │ │
│ │ ┌──────────────┐ ┌──────────────┐ │ │
│ │ │ファイルシステム│ │ ネットワーク │ │ │
│ │ └──────────────┘ └──────────────┘ │ │
│ │ ┌──────────────┐ ┌──────────────┐ │ │
│ │ │デバイスドライバ│ │ セキュリティ │ │ │
│ │ └──────────────┘ └──────────────┘ │ │
│ └─────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ハードウェア (CPU, メモリ, ディスク, NIC) │
│ │
└─────────────────────────────────────────────────────────────┘

なぜカーネルが必要か

┌─────────────────────────────────────────────────────────────┐
│ カーネルがないと何が起きるか │
├─────────────────────────────────────────────────────────────┤
│ │
│ 【問題1: ハードウェアの直接操作】 │
│ │
│ カーネルなし: │
│ - 各プログラムがCPU、メモリ、ディスクを直接操作 │
│ - プログラムAがメモリを使い切ると、Bが動けない │
│ - ディスクを同時に書き込むとデータ破損 │
│ │
│ カーネルあり: │
│ - カーネルがリソースを公平に配分 │
│ - プログラム同士が干渉しない │
│ │
│ │
│ 【問題2: セキュリティ】 │
│ │
│ カーネルなし: │
│ - どのプログラムでも全データにアクセス可能 │
│ - 悪意あるプログラムがシステムを破壊できる │
│ │
│ カーネルあり: │
│ - 権限チェックで不正アクセスを防ぐ │
│ - ユーザーごとにアクセス制限 │
│ │
│ │
│ 【問題3: 抽象化】 │
│ │
│ カーネルなし: │
│ - プログラムがハードウェアの種類ごとに対応必要 │
│ - HDD用、SSD用、NVMe用...と別々のコードが必要 │
│ │
│ カーネルあり: │
│ - 「ファイル」という統一インターフェース │
│ - プログラムはハードウェアを意識しない │
│ │
└─────────────────────────────────────────────────────────────┘

システムコール

アプリケーションがカーネルの機能を使うときは、システムコールを呼び出します:

┌─────────────────────────────────────────────────────────────┐
│ システムコールの例 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 【ファイル操作】 │
│ open() - ファイルを開く │
│ read() - ファイルを読む │
│ write() - ファイルに書く │
│ close() - ファイルを閉じる │
│ │
│ 【プロセス操作】 │
│ fork() - プロセスを複製 │
│ exec() - プログラムを実行 │
│ exit() - プロセスを終了 │
│ wait() - 子プロセスの終了を待つ │
│ │
│ 【メモリ操作】 │
│ mmap() - メモリをマッピング │
│ brk() - ヒープ領域を拡張 │
│ │
│ 【ネットワーク操作】 │
│ socket() - ソケットを作成 │
│ connect()- サーバーに接続 │
│ send() - データを送信 │
│ recv() - データを受信 │
│ │
│ │
│ 例: cat file.txt の内部動作 │
│ ┌────────────────────────────────────────────────────┐ │
│ │ 1. open("file.txt") → カーネルがファイルを開く │ │
│ │ 2. read(fd, buf) → カーネルが内容を読み込み │ │
│ │ 3. write(stdout) → カーネルが画面に出力 │ │
│ │ 4. close(fd) → カーネルがファイルを閉じる │ │
│ └────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘

ユーザー空間とカーネル空間

┌─────────────────────────────────────────────────────────────┐
│ ユーザー空間とカーネル空間 │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ ユーザー空間 │ │
│ │ │ │
│ │ - 通常のプログラムが動作する場所 │ │
│ │ - 制限されたメモリにしかアクセスできない │ │
│ │ - ハードウェアに直接アクセスできない │ │
│ │ - クラッシュしても他に影響しにくい │ │
│ │ │ │
│ │ 実行されるもの: │ │
│ │ nginx, postgres, bash, vim, ls, grep... │ │
│ └─────────────────────────────────────────────────────┘ │
│ │ │
│ システムコール │
│ │ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ カーネル空間 │ │
│ │ │ │
│ │ - 特権モードで動作 │ │
│ │ - 全メモリにアクセス可能 │ │
│ │ - ハードウェアを直接制御 │ │
│ │ - クラッシュ = システム全体が停止 │ │
│ │ │ │
│ │ 実行されるもの: │ │
│ │ カーネル本体、デバイスドライバ、ファイルシステム │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ │
│ この分離により: │
│ - 一般プログラムのバグがシステムを壊さない │
│ - セキュリティが保たれる │
│ - 安定性が向上する │
│ │
└─────────────────────────────────────────────────────────────┘

カーネルの主な機能

機能説明関連ドキュメント
プロセス管理プロセスの作成、スケジューリング、終了プロセス管理
メモリ管理仮想メモリ、ページング、メモリ割り当て-
ファイルシステムファイル操作、ディレクトリ管理ファイルシステム
ネットワークTCP/IP、ソケット、ネットワークデバイスネットワーク基礎
デバイス管理ハードウェアドライバ、デバイスファイル-
セキュリティ権限管理、SELinux、capabilitiesユーザーと権限

カーネルとコンテナ

Dockerコンテナはホストのカーネルを共有しています:

┌─────────────────────────────────────────────────────────────┐
│ カーネルとコンテナの関係 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 【仮想マシン(VM)】 【コンテナ(Docker)】 │
│ │
│ ┌────────────────┐ ┌────────────────┐ │
│ │ アプリA │ │ アプリA │ │
│ ├────────────────┤ ├────────────────┤ │
│ │ ゲストOS │ │ コンテナ │ │
│ │ (カーネル含む) │ │ (カーネルなし) │ │
│ ├────────────────┤ └───────┬────────┘ │
│ │ ハイパーバイザ │ │ │
│ ├────────────────┤ │ │
│ │ ホストOS │ ┌───────┴────────┐ │
│ │ (カーネル) │ │ ホストOS │ │
│ └────────────────┘ │ (カーネル共有) │ │
│ └────────────────┘ │
│ 各VMが独自のカーネル 全コンテナが1つのカーネル │
│ → 重い、起動遅い → 軽い、起動速い │
│ │
│ │
│ コンテナがカーネルを共有する影響: │
│ ┌────────────────────────────────────────────────────┐ │
│ │ - コンテナ内で uname -r するとホストのカーネル │ │
│ │ - カーネルのバグは全コンテナに影響 │ │
│ │ - Linuxコンテナは Linux カーネル上でのみ動作 │ │
│ │ - Namespaces, cgroups はカーネルの機能 │ │
│ └────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘
# カーネルバージョンの確認
uname -r
# 例: 5.15.0-91-generic

# コンテナ内でも同じカーネルバージョン
docker run alpine uname -r
# 例: 5.15.0-91-generic ← ホストと同じ

ディストリビューション

主要なディストリビューション

┌─────────────────────────────────────────────────────────────┐
│ Linux ディストリビューション │
├─────────────────────────────────────────────────────────────┤
│ │
│ Debian系 │
│ ├── Debian 安定性重視、サーバー向け │
│ ├── Ubuntu デスクトップ/サーバー、広く使われる │
│ └── Alpine 軽量、コンテナ向け(musl libc) │
│ │
│ Red Hat系 │
│ ├── RHEL エンタープライズ、商用サポート │
│ ├── CentOS/Rocky RHEL互換、無償 │
│ ├── Fedora 最新技術、開発者向け │
│ └── Amazon Linux AWS最適化 │
│ │
│ その他 │
│ ├── Arch Linux 最新、ローリングリリース │
│ └── openSUSE ヨーロッパで人気 │
│ │
└─────────────────────────────────────────────────────────────┘

コンテナでよく使われるベースイメージ

イメージサイズ特徴
alpine~5MB最小、musl libc
debian:slim~70MB標準的なツール
ubuntu~80MB豊富なパッケージ
amazonlinux~150MBAWS向け
distroless最小限シェルなし、セキュア

パッケージ管理

# Debian/Ubuntu (apt)
apt update
apt install nginx
apt remove nginx
apt search nginx

# RHEL/CentOS (dnf/yum)
dnf update
dnf install nginx
dnf remove nginx
dnf search nginx

# Alpine (apk)
apk update
apk add nginx
apk del nginx
apk search nginx

シェルの基礎

シェルとは

シェルは、ユーザーとカーネルの間のインターフェースです。

┌─────────────────────────────────────────────────────────────┐
│ │
│ ユーザー ──► コマンド入力 ──► シェル ──► カーネル │
│ │ │
│ ▼ │
│ コマンド解釈 │
│ パイプ処理 │
│ リダイレクト │
│ 変数展開 │
│ │
└─────────────────────────────────────────────────────────────┘

主なシェル

シェル説明
bash最も一般的、多くのディストリビューションでデフォルト
shPOSIX準拠、スクリプト互換性が高い
zsh高機能、macOSのデフォルト
ash/dash軽量、Alpineで使用

現在のシェル確認

# 現在のシェル
echo $SHELL

# 使用可能なシェル
cat /etc/shells

# シェルの変更
chsh -s /bin/zsh

基本的なシェル操作

# コマンド履歴
history
!123 # 履歴番号123を実行
!! # 直前のコマンドを実行
!$ # 直前のコマンドの最後の引数

# タブ補完
cd /etc/sys<Tab> # 自動補完

# キーボードショートカット
Ctrl + C # 実行中のコマンドを中断
Ctrl + D # EOF(シェル終了)
Ctrl + Z # バックグラウンドに送る
Ctrl + L # 画面クリア
Ctrl + R # 履歴検索
Ctrl + A # 行頭に移動
Ctrl + E # 行末に移動

環境変数

環境変数とは

環境変数は、プロセスに渡される設定値です。

プロセスが動作するための設定情報(パス、言語設定、認証情報など)を保持します。親プロセスから子プロセスに継承されます。

┌─────────────────────────────────────────────────────────────┐
│ 環境変数の仕組み │
├─────────────────────────────────────────────────────────────┤
│ │
│ 【環境変数の継承】 │
│ │
│ bash (親プロセス) │
│ ├── PATH=/usr/bin:/bin │
│ ├── HOME=/home/user │
│ └── LANG=ja_JP.UTF-8 │
│ │ │
│ │ fork + exec │
│ ▼ │
│ nginx (子プロセス) │
│ ├── PATH=/usr/bin:/bin ← 継承 │
│ ├── HOME=/home/user ← 継承 │
│ └── LANG=ja_JP.UTF-8 ← 継承 │
│ │
│ │
│ 【シェル変数 vs 環境変数】 │
│ │
│ シェル変数: FOO=bar ← そのシェルだけで有効 │
│ 環境変数: export FOO=bar ← 子プロセスにも継承 │
│ │
└─────────────────────────────────────────────────────────────┘

重要な環境変数

変数説明
PATHコマンドを探すディレクトリ/usr/bin:/bin
HOMEホームディレクトリ/home/user
USERユーザー名user
SHELLログインシェル/bin/bash
LANG言語設定ja_JP.UTF-8
TERMターミナルタイプxterm-256color
PWDカレントディレクトリ/home/user/work
EDITORデフォルトエディタvim

環境変数の操作

# 環境変数の確認
echo $PATH
echo $HOME
printenv # 全環境変数を表示
env # 全環境変数を表示

# 環境変数の設定(現在のシェルのみ)
export MY_VAR="hello"

# 一時的に環境変数を設定してコマンド実行
MY_VAR=hello ./script.sh
env MY_VAR=hello ./script.sh

# 永続的に設定(シェル起動時に読み込まれる)
# ~/.bashrc または ~/.bash_profile に追記
echo 'export MY_VAR="hello"' >> ~/.bashrc
source ~/.bashrc # 再読み込み

PATH の仕組み

┌─────────────────────────────────────────────────────────────┐
│ PATH の動作 │
├─────────────────────────────────────────────────────────────┤
│ │
│ PATH=/usr/local/bin:/usr/bin:/bin │
│ │
│ $ ls と入力すると... │
│ │
│ 1. /usr/local/bin/ls を探す → なし │
│ 2. /usr/bin/ls を探す → なし │
│ 3. /bin/ls を探す → 見つかった! → 実行 │
│ │
│ │
│ 【PATHの追加】 │
│ export PATH=$PATH:/my/custom/bin ← 末尾に追加 │
│ export PATH=/my/custom/bin:$PATH ← 先頭に追加(優先) │
│ │
│ │
│ 【コマンドの場所確認】 │
│ $ which python │
│ /usr/bin/python │
│ │
│ $ type python │
│ python is /usr/bin/python │
│ │
└─────────────────────────────────────────────────────────────┘

コンテナと環境変数

# Dockerfile で環境変数を設定
ENV APP_ENV=production
ENV DATABASE_URL=postgres://localhost/db

# docker run で環境変数を渡す
docker run -e APP_ENV=production myapp
docker run --env-file .env myapp

# Kubernetes で環境変数を設定
# spec.containers[].env または ConfigMap/Secret から
┌─────────────────────────────────────────────────────────────┐
│ コンテナでの環境変数の使い方 │
├─────────────────────────────────────────────────────────────┤
│ │
│ よく使われるパターン: │
│ │
│ - DATABASE_URL : DB接続情報 │
│ - API_KEY : 認証キー(SecretやVaultから) │
│ - LOG_LEVEL : ログレベル (debug/info/error) │
│ - APP_ENV : 環境 (development/staging/production) │
│ - PORT : リッスンポート │
│ │
│ 注意: │
│ - 機密情報は docker run -e より Secret を使う │
│ - 環境変数は ps コマンドで見える場合がある │
│ │
└─────────────────────────────────────────────────────────────┘

標準入出力

標準入出力とは

すべてのプロセスは、生成時に3つの入出力チャネルを持ちます:

┌─────────────────────────────────────────────────────────────┐
│ 標準入出力 │
├─────────────────────────────────────────────────────────────┤
│ │
│ ┌────────────┐ │
│ │ キーボード │ ───► stdin (標準入力) ───┐ │
│ └────────────┘ fd=0 │ │
│ ▼ │
│ ┌────────────┐ │
│ │ プロセス │ │
│ └────────────┘ │
│ │ │ │
│ ┌────────────┐ │ │ │
│ │ 画面 │ ◄── stdout (標準出力)┘ │ │
│ │ (正常出力) │ fd=1 │ │
│ └────────────┘ │ │
│ │ │
│ ┌────────────┐ │ │
│ │ 画面 │ ◄── stderr (標準エラー出力) ─┘ │
│ │ (エラー) │ fd=2 │
│ └────────────┘ │
│ │
│ │
│ fd = ファイルディスクリプタ(後述) │
│ │
└─────────────────────────────────────────────────────────────┘
名前fdデフォルト用途
stdin0キーボードプログラムへの入力
stdout1画面正常な出力
stderr2画面エラーメッセージ

なぜ stdout と stderr を分けるのか

┌─────────────────────────────────────────────────────────────┐
│ stdout と stderr の分離 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 【理由:出力先を別々に制御できる】 │
│ │
│ 例: 正常出力だけファイルに保存、エラーは画面に表示 │
│ │
│ $ ./process > output.txt │
│ │
│ output.txt には stdout のみ保存 │
│ stderr は画面に表示される │
│ │
│ │
│ 【実例】 │
│ │
│ $ find / -name "*.conf" > files.txt │
│ │
│ files.txt: 見つかったファイル一覧(stdout) │
│ 画面: Permission denied エラー(stderr) │
│ │
└─────────────────────────────────────────────────────────────┘

リダイレクト

# stdout をファイルに(上書き)
command > file.txt

# stdout をファイルに(追記)
command >> file.txt

# stderr をファイルに
command 2> error.txt

# stdout と stderr を同じファイルに
command > all.txt 2>&1
command &> all.txt # bash の省略形

# stdout と stderr を別々のファイルに
command > out.txt 2> err.txt

# 出力を捨てる
command > /dev/null # stdout を捨てる
command 2> /dev/null # stderr を捨てる
command > /dev/null 2>&1 # 両方捨てる

# stdin をファイルから
command < input.txt

パイプ

パイプ | は、あるコマンドの stdout を次のコマンドの stdin に接続します:

┌─────────────────────────────────────────────────────────────┐
│ パイプの仕組み │
├─────────────────────────────────────────────────────────────┤
│ │
│ $ cat file.txt | grep "error" | wc -l │
│ │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │ cat │ │ grep │ │ wc │ │
│ │ │ │ │ │ │ │
│ │ stdout ─┼──►──┼ stdin │ │ │ │
│ │ │ │ stdout ─┼──►──┼ stdin │ │
│ └─────────┘ └─────────┘ │ stdout ─┼──► 画面 │
│ └─────────┘ │
│ │
│ 注意: パイプは stdout のみを渡す │
│ stderr はパイプを通らず画面に出る │
│ │
│ stderr もパイプに渡したい場合: │
│ $ command 2>&1 | grep "pattern" │
│ │
└─────────────────────────────────────────────────────────────┘

ファイルディスクリプタ

ファイルディスクリプタ(fd)は、プロセスが開いているファイルへの参照番号です。

┌─────────────────────────────────────────────────────────────┐
│ ファイルディスクリプタ │
├─────────────────────────────────────────────────────────────┤
│ │
│ プロセス │
│ ┌────────────────────────────────────────────────────┐ │
│ │ │ │
│ │ fd 0 ───► stdin (キーボード) │ │
│ │ fd 1 ───► stdout (画面) │ │
│ │ fd 2 ───► stderr (画面) │ │
│ │ fd 3 ───► /var/log/app.log (ログファイル) │ │
│ │ fd 4 ───► ソケット (ネットワーク接続) │ │
│ │ fd 5 ───► /tmp/data.txt │ │
│ │ ... │ │
│ │ │ │
│ └────────────────────────────────────────────────────┘ │
│ │
│ 0, 1, 2 は予約済み(標準入出力) │
│ 3 以降はプログラムが開いたファイル │
│ │
│ │
│ 【確認方法】 │
│ $ ls -l /proc/<PID>/fd/ │
│ │
│ lrwx------ 0 -> /dev/pts/0 (stdin: ターミナル) │
│ lrwx------ 1 -> /dev/pts/0 (stdout: ターミナル) │
│ lrwx------ 2 -> /dev/pts/0 (stderr: ターミナル) │
│ lr-x------ 3 -> /var/log/app.log (開いたファイル) │
│ │
└─────────────────────────────────────────────────────────────┘

リダイレクトの内部動作

┌─────────────────────────────────────────────────────────────┐
│ command > file.txt の内部動作 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 通常: │
│ fd 1 ───► /dev/pts/0 (ターミナル) │
│ │
│ リダイレクト後: │
│ fd 1 ───► file.txt │
│ │
│ プログラムは fd 1 に書き込むだけ │
│ → 出力先が変わったことを意識しない │
│ → これが「抽象化」の力 │
│ │
│ │
│ 【2>&1 の意味】 │
│ 「fd 2 を fd 1 と同じ場所に向ける」 │
│ │
│ command > file.txt 2>&1 │
│ │
│ fd 1 ───► file.txt │
│ fd 2 ───► (fd 1 と同じ) ───► file.txt │
│ │
└─────────────────────────────────────────────────────────────┘

仮想メモリ

仮想メモリとは

仮想メモリは、各プロセスに専用のメモリ空間があるように見せる仕組みです。

実際の物理メモリ(RAM)をカーネルが管理し、プロセスには「仮想的な」アドレス空間を提供します。

┌─────────────────────────────────────────────────────────────┐
│ 仮想メモリの仕組み │
├─────────────────────────────────────────────────────────────┤
│ │
│ 【各プロセスから見える世界】 │
│ │
│ プロセスA プロセスB プロセスC │
│ ┌───────────┐ ┌───────────┐ ┌───────────┐ │
│ │ 0x0000 │ │ 0x0000 │ │ 0x0000 │ │
│ │ ... │ │ ... │ │ ... │ │
│ │ 0xFFFF │ │ 0xFFFF │ │ 0xFFFF │ │
│ └───────────┘ └───────────┘ └───────────┘ │
│ 「自分専用の 「自分専用の 「自分専用の │
│ 広いメモリ」 広いメモリ」 広いメモリ」 │
│ │ │ │ │
│ └────────────────────┼────────────────────┘ │
│ ▼ │
│ ┌─────────────┐ │
│ │ カーネル │ │
│ │ (MMU管理) │ │
│ └──────┬──────┘ │
│ ▼ │
│ ┌─────────────────────────────┐ │
│ │ 物理メモリ (RAM) │ │
│ │ 実際は限られた容量 │ │
│ └─────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘

なぜ仮想メモリが必要か

┌─────────────────────────────────────────────────────────────┐
│ 仮想メモリのメリット │
├─────────────────────────────────────────────────────────────┤
│ │
│ 1. 分離(セキュリティ) │
│ ┌─────────────────────────────────────────────────┐ │
│ │ プロセスAは自分のメモリしか見えない │ │
│ │ → プロセスBのメモリを読み書きできない │ │
│ │ → 悪意あるプログラムから保護 │ │
│ └─────────────────────────────────────────────────┘ │
│ │
│ 2. 大きなメモリ空間 │
│ ┌─────────────────────────────────────────────────┐ │
│ │ 物理メモリ: 8GB │ │
│ │ 各プロセス: 「自分には128TBのメモリがある」 │ │
│ │ → 実際に使う分だけ物理メモリを割り当て │ │
│ └─────────────────────────────────────────────────┘ │
│ │
│ 3. メモリの効率的な利用 │
│ ┌─────────────────────────────────────────────────┐ │
│ │ - 使用中のメモリだけ物理メモリに配置 │ │
│ │ - 使っていないメモリはディスクに退避(スワップ)│ │
│ │ - 同じプログラムのコードは共有 │ │
│ └─────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────┘

プロセスのメモリレイアウト

┌─────────────────────────────────────────────────────────────┐
│ プロセスの仮想メモリ空間 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 高アドレス │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ カーネル空間 │ │
│ │ (ユーザーからアクセス不可) │ │
│ ├─────────────────────────────────────────────────────┤ │
│ │ スタック │ │
│ │ (関数呼び出し、ローカル変数) │ │
│ │ ↓ 下に成長 │ │
│ ├─────────────────────────────────────────────────────┤ │
│ │ (空き領域) │ │
│ ├─────────────────────────────────────────────────────┤ │
│ │ ↑ 上に成長 │ │
│ │ ヒープ │ │
│ │ (malloc等で動的に確保) │ │
│ ├─────────────────────────────────────────────────────┤ │
│ │ BSS │ │
│ │ (未初期化のグローバル変数) │ │
│ ├─────────────────────────────────────────────────────┤ │
│ │ データ │ │
│ │ (初期化済みグローバル変数) │ │
│ ├─────────────────────────────────────────────────────┤ │
│ │ テキスト │ │
│ │ (プログラムのコード) │ │
│ └─────────────────────────────────────────────────────┘ │
│ 低アドレス │
│ │
└─────────────────────────────────────────────────────────────┘

スワップ

物理メモリが不足すると、使っていないメモリをディスクに退避します:

┌─────────────────────────────────────────────────────────────┐
│ スワップの仕組み │
├─────────────────────────────────────────────────────────────┤
│ │
│ 物理メモリ (RAM) 8GB │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ プロセスA │ プロセスB │ プロセスC │ プロセスD │ │
│ │ 2GB │ 2GB │ 2GB │ 2GB │ │
│ └─────────────────────────────────────────────────────┘ │
│ ↑ │
│ │ メモリ不足!新しいプロセスEを起動したい │
│ ▼ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ カーネル: 「プロセスAは最近使ってないな...」 │ │
│ │ 「ディスクに退避しよう(スワップアウト)」 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ スワップ領域 (ディスク) │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ プロセスAのメモリ内容 │ │
│ └─────────────────────────────────────────────────────┘ │
│ │
│ プロセスAが再度アクセスされると: │
│ → スワップイン(ディスクからメモリに戻す) │
│ → この入れ替えが頻発すると「スラッシング」で遅くなる │
│ │
└─────────────────────────────────────────────────────────────┘
# メモリとスワップの確認
free -h

# total used free shared buff/cache available
# Mem: 7.7Gi 3.2Gi 1.1Gi 512Mi 3.4Gi 3.7Gi
# Swap: 2.0Gi 100Mi 1.9Gi

コンテナとメモリ

┌─────────────────────────────────────────────────────────────┐
│ コンテナのメモリ制限 │
├─────────────────────────────────────────────────────────────┤
│ │
│ docker run --memory=512m myapp │
│ │
│ → cgroups を使ってメモリ使用量を制限 │
│ → 制限を超えると OOM Killer がプロセスを強制終了 │
│ │
│ Kubernetes: │
│ resources: │
│ requests: │
│ memory: "256Mi" # 最低保証 │
│ limits: │
│ memory: "512Mi" # 上限 │
│ │
└─────────────────────────────────────────────────────────────┘

基本的なコマンド操作

ナビゲーション

# 現在のディレクトリ
pwd

# ディレクトリ移動
cd /var/log
cd .. # 親ディレクトリ
cd ~ # ホームディレクトリ
cd - # 直前のディレクトリ

# ディレクトリ内容
ls
ls -la # 詳細表示、隠しファイル含む
ls -lh # サイズを読みやすく
ls -lt # 更新日時順

ファイル操作

# ファイル作成
touch file.txt
echo "content" > file.txt

# ファイルコピー
cp source.txt dest.txt
cp -r dir1 dir2 # ディレクトリ

# ファイル移動/リネーム
mv old.txt new.txt
mv file.txt /path/to/

# ファイル削除
rm file.txt
rm -r directory # ディレクトリ
rm -rf directory # 強制削除(注意)

# ディレクトリ作成
mkdir newdir
mkdir -p path/to/newdir # 親も作成

ファイル内容の確認

# 全内容表示
cat file.txt

# ページング
less file.txt
more file.txt

# 先頭/末尾
head -n 20 file.txt
tail -n 20 file.txt
tail -f file.txt # リアルタイム監視

# 行数/単語数
wc -l file.txt

パイプとリダイレクト

# パイプ(コマンドの出力を次のコマンドへ)
cat file.txt | grep "pattern"
ps aux | grep nginx | wc -l

# リダイレクト
echo "text" > file.txt # 上書き
echo "text" >> file.txt # 追記
command 2> error.log # 標準エラーをファイルへ
command > out.txt 2>&1 # 標準出力とエラーを同じファイルへ
command < input.txt # ファイルを標準入力として使用

# /dev/null(出力を捨てる)
command > /dev/null 2>&1

検索

# ファイル検索
find /path -name "*.txt"
find /path -type f -mtime -7 # 7日以内に更新

# ファイル内容検索
grep "pattern" file.txt
grep -r "pattern" /path # 再帰的に検索
grep -i "pattern" file.txt # 大文字小文字を無視
grep -v "pattern" file.txt # マッチしない行

# コマンド検索
which nginx
whereis nginx
type ls

ヘルプの使い方

manページ

# マニュアル表示
man ls
man 5 passwd # セクション5(ファイル形式)

# マニュアルセクション
# 1: ユーザーコマンド
# 2: システムコール
# 3: ライブラリ関数
# 5: ファイル形式
# 8: システム管理コマンド

# キーワード検索
man -k keyword
apropos keyword

その他のヘルプ

# ビルトインヘルプ
help cd # bash ビルトイン

# コマンドのヘルプオプション
ls --help

# info(詳細なドキュメント)
info coreutils

# tldr(実用的な例)
# https://tldr.sh/
tldr tar

コンテナとの関係

Dockerで使われるLinux機能

┌─────────────────────────────────────────────────────────────┐
│ Docker が使う Linux カーネル機能 │
├─────────────────────────────────────────────────────────────┤
│ │
│ Namespaces(名前空間) │
│ └── プロセス、ネットワーク、ファイルシステムの分離 │
│ │
│ cgroups(コントロールグループ) │
│ └── CPU、メモリ、I/Oのリソース制限 │
│ │
│ Union File System(OverlayFS) │
│ └── レイヤー構造のファイルシステム │
│ │
│ Capabilities │
│ └── rootの権限を細分化 │
│ │
│ seccomp │
│ └── システムコールの制限 │
│ │
└─────────────────────────────────────────────────────────────┘

コンテナ内でのLinuxコマンド

# コンテナ内でシェルを起動
docker exec -it container-name /bin/sh

# Alpine(ash)
docker run -it alpine /bin/sh

# コンテナ内の情報確認
cat /etc/os-release # OS情報
uname -a # カーネル情報
hostname # ホスト名
id # ユーザー情報

デバッグ用コンテナ

# busybox(軽量ツール集)
docker run -it busybox

# netshoot(ネットワークデバッグ)
docker run -it --network container:target nicolaka/netshoot

# Kubernetesでのデバッグ
kubectl debug pod-name -it --image=busybox

まとめ

最低限覚えるべきコマンド

カテゴリコマンド
ナビゲーションpwd, cd, ls
ファイル操作cp, mv, rm, mkdir, touch
内容確認cat, less, head, tail
検索find, grep
プロセスps, top, kill
ネットワークping, curl, netstat

次のステップ


参考リソース