Skip to content

Instantly share code, notes, and snippets.

@showa-yojyo
Last active September 7, 2025 13:06
Show Gist options
  • Select an option

  • Save showa-yojyo/caf7c68a253184fd07ac5e78cf9270f8 to your computer and use it in GitHub Desktop.

Select an option

Save showa-yojyo/caf7c68a253184fd07ac5e78cf9270f8 to your computer and use it in GitHub Desktop.
オライリージャパンの『入門モダン Linux』の読書メモをテキストファイルに写したもの
date title
2025-09-07
『入門モダン Linux』読書ノート

関連サイト:

※手書きのメモから書き起こし中。浄書は後ほど行う。

1 章 Linux の入門

1.1 モダンな環境とは何か?

Linux は現代的な分野(モバイル機器、クラウドコンピューティング、IoT, 等々)で動作していたり、使われていたりする。

1.2 これまでの Linux の歴史

1990 年代から 2010 年代まで、現在に至る Linux の歴史が要約されている。この前読んだ TAOUP の部分史と言える。

1.3 なぜオペレーティングシステムなのか?

OS を利用することで《リソースを自分で管理する必要がなくなり、ビジネスロジックに集中でき》るようになる。

1.4 Linux ディストリビューション

Linux という言葉は次の二つの意味のどちらかを表すのが通例だ:

  • Linux カーネル:すなわちシステムコールとデバイスドライバーの集合。
  • Linux ディストリビューション:カーネル、パッケージ管理、関連コンポーネント、等々を一括りにして呼ぶ。

1.5 リソースの可視性

本書ではリソースとはソフトウェア実行の支援のために使用できるすべてのものと定義している。 ハードウェア、ファイルシステム、ドライブ、プロセス、ネットワークデバイス、等々だ。

  • コマンド cat /proc/version は Linux のバージョンを出力する。
  • コマンド cat /proc/cpuinfo は CPU 情報を出力する。 ちなみに cat ではなく bat を使うと少し見やすい。
  • コマンド cat /proc/$$/status は自プロセスの状態を出力する。

この節の後半の記述がたいせつだ。6 章と 9 章で詳しく議論される。

1.6 Linux の全体像

図 1-1 を頭に入れておく。本書はこの図式の下層から上層に向かって議論を展開する。

Linux は POSIX, System V におおよそ準拠するようにしている。

1.7 まとめ

本書は各章の最後に関連資料を提示しているので、気になるものを閲覧するといい。

2 章 Linux カーネル

カーネル自体は OS ではなく、その中心部分に過ぎない。

2.1 Linux アーキテクチャ

三階層構成を意識する。下層から上層に向かって:

  • ハードウェア
  • カーネル
  • ユーザー空間

各層間にはインターフェイスがある。ハードウェアとカーネルの間のインターフェイスはハードウェアごとに異なる。 カーネルとユーザー空間のインターフェイスはシステムコールだ。

TODO: ユーザー空間にはユーザーモードとカーネルモードの二つがある?

2.2 CPU アーキテクチャ

  • Linux は数多くの CPU アーキテクチャーの上で動作する。
  • 現代的環境では BIOS は UEFI に置き換わっている。
  • BIOS からハード情報を得る方法はいくつかある:
    • コマンド dmidecode; 環境によってはろくな出力がない可能性がある。
    • コマンド lscpu
    • 先述した cat /proc/cpuinfo
    • コマンド uname -m
$ uname -m
x86_64

2.2.1 x86 アーキテクチャ

TBR

2.2.2 ARM アーキテクチャ

ノート割愛。

2.2.3 RISC-V アーキテクチャ

ノート割愛。

2.3 カーネルコンポーネント

  • Linux カーネルは一枚岩であり、コンポーネント全てが単一バイナリーに収まっている。
  • その部品とは、プロセス管理、メモリー管理、ネットワーク、ファイルシステム、デバイスドライバーだ。

2.3.1 プロセス管理

プロセス一つは実行プログラム一つに対応するのが一般的だ。スレッドはプロセス内のコードを実行する単位だ。マルチスレッドプログラムを考えるといい。

術語としてのセッション、プロセスグループ、プロセス、スレッド、タスクを理解するのが必須。

  • コマンド ps -j で現セッションにあるプロセス情報を出力する。
  • コマンド ls -al /proc/nnnn/task/nnnn でタスクの情報を出力する。これは詳しく知りたい。

2.3.2 メモリ管理

TLB: 仮想メモリーを物理メモリーに変換する仕組み。 頻繁にアクセスされるアドレス変換情報を保持し、ページテーブルへのアクセスを減らすことでシステムの性能を向上させる。

例えば 64 ビット Linux では一プロセス当たり最大 128 TB の仮想アドレス空間、合計約 64 TB の物理メモリー (RAM) の使用が可能。

ファイル /proc/meminfo にメモリー関連の情報がある。

2.3.3 ネットワーク

カーネルにおけるネットワークに対する役割は次の三つしかない:

  • ソケット
  • TCP および UDP
  • IP

ネットワークに関してよく使うコマンドは ip だ。

  • コマンド ip link でネットワークインターフェイスの情報を出力する。
  • コマンド ip route でルーティング情報を出力する。

2.3.4 ファイルシステム

  • ファイルシステムには ext4, btrfs, NTFS, etc. などがある。
  • VFS はこのような異なるファイルシステムを統一的に扱うための抽象化だ。

詳しくは 5 章で議論される。

2.3.5 デバイスドライバ

デバイスドライバーとは《カーネルで動作する小規模なコード》だ。

デバイスドライバーは (1) カーネルに静的に組み込まれるか、(2) カーネルモジュールとして組み込まれ、必要時に動的にカーネルにロードされる。

  • コマンド ls -al /sys/devices で Linux システム上のデバイスを確認できる。
  • コマンド mount で「マウントされている」デバイス一覧を出力する。

TODO: これらの出力の読み方がわからない。

2.3.6 システムコール

  • カーネルモードとユーザー空間モードの切り替えは時間的コストがかかる。
  • コマンド strace ls を試してみよう。どんなシステムコールが発行されているのかが見える。 コマンド strace -c curl -s $URL > /dev/null も試してみよう。

オプション -c は要約のみを出力する。こちらのほうが見やすい。

$ strace -c curl -s https://example.com/ > /dev/null
% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
 29.40    0.005306          34       155           mmap
 16.49    0.002976          28       103           read
  9.89    0.001785          30        58         4 openat
  7.02    0.001267          17        74           rt_sigaction
  6.73    0.001215          19        62           close
  6.34    0.001144          20        57           fstat
  5.21    0.000941          27        34           mprotect
  4.43    0.000799          33        24           poll
  2.70    0.000488         488         1           execve
  1.80    0.000324          12        26           brk
  1.69    0.000305          19        16           getpid
  1.52    0.000275           8        31         7 recvfrom
  0.64    0.000116          19         6           sendto
  0.53    0.000096          10         9           fcntl
  0.51    0.000092          23         4           socket
  0.51    0.000092          18         5           getsockname
  0.45    0.000081          27         3         3 connect
  0.44    0.000080          20         4           setsockopt
  0.35    0.000063          63         1           clone3
  0.34    0.000062           2        23           futex
  0.30    0.000055          27         2           pread64
  0.29    0.000053          53         1         1 access
  0.27    0.000049          16         3         2 ioctl
  0.26    0.000047          23         2           pipe2
  0.25    0.000045          15         3           getpeername
  0.22    0.000040          10         4         1 newfstatat
  0.22    0.000039          13         3           rt_sigprocmask
  0.16    0.000029          29         1           arch_prctl
  0.16    0.000029          29         1           set_robust_list
  0.16    0.000028          28         1           set_tid_address
  0.16    0.000028          28         1           rseq
  0.13    0.000023          23         1           getsockopt
  0.11    0.000020           6         3           getrandom
  0.10    0.000018          18         1           write
  0.10    0.000018           6         3           lseek
  0.10    0.000018          18         1           geteuid
  0.00    0.000000           0         1           munmap
  0.00    0.000000           0         1           prlimit64
------ ----------- ----------- --------- --------- ----------------
100.00    0.018046          24       729        18 total

2.4 カーネルの拡張

カーネルのバージョンを得るにはコマンド uname -srm を実行するのもいい。

$ uname -srm
Linux 5.15.153.1-microsoft-standard-WSL2 x86_64

2.4.1 モジュール

  • 必要に応じてカーネルにロードできるプログラムがモジュールだ。
  • コマンド find /lib/modules/$(uname -r) -type f -name '*.ko*' で利用可能なモジュールを見る。
  • コマンド lsmod でカーネルがロードしているモジュールを見る。このコマンドはファイル /etc/modules から情報を得る。
  • コマンド modprobe はモジュールを取り扱うのに用いる。細やかなオプション指定が求められる。

2.4.2 モダンなカーネル拡張:eBPF

システムコール bpf を用いた、Linux カーネル機能を安全かつ効率的に拡張できる Linux 機能だ。

2.5 まとめ

TODO: 何を読みたい?

3 章 シェルとスクリプト

  • CLI の観点からは、Linux と対話する方法は二つある。手動またはスクリプトだ。
  • スクリプトを開発したり、保守したりするのに時間をかけ過ぎてはならない。

3.1 基本用語

3.1.1 ターミナル

  • 環境変数 TERM
  • コマンド infocmp: これは読み方が不明であり過ぎる。
  • 新世代のターミナル
$ printenv TERM
xterm-256color

3.1.2 シェル

自分がどのシェルを使っているかを知る手段を複数知っておく:

  • file -h
  • echo $0
  • echo $SHELL

以降の記述では、明示がない限り bash が使われるものとする。

3.1.2.1 ストリーム

おなじみの内容なので割愛。

3.1.2.2 変数
3.1.2.3 終了ステータス

パイプラインで終了ステータスを処理するには変数 PIPESTATUS を用いる。

3.1.2.4 ビルトインコマンド
  • コマンド help で一覧出力されるコマンド群が Bash 組み込みのコマンドだ。
  • POSIX によるならば which よりも command -v のほうが望ましい。
3.1.2.5 ジョブ制御
  • バックグラウンド実行をモノにしたい。
    • アンドマークを付けて実行したり、
    • フォアグラウンド実行してから C-z を押す。
  • ターミナルが閉じても実行を続けさせたいコマンドには nohup を使え。
  • TODO: disown をちゃんと調べる。

ジョブ制御よりも後述のターミナルマルチプレクサを使え。

3.1.3 モダンなコマンド

よく使われるコマンドには現代的変種が存在する。付録 B を見ろ。

3.1.3.1 exa

導入した。

3.1.3.2 bat

導入済み。

3.1.3.3 rg

いちおうインストールしてチュートリアルも行った。

オプション -g が便利なので、これを単品でプログラム化して欲しい。

3.1.3.4 jq

導入済み。習得に時間がかかるように思える。

この小節の最後に資料 modern-unix https://github.com/ibraheemdev/modern-unix を紹介している。

3.1.4 一般的なタスク

3.1.4.1 よく使うコマンドを短くする

シェルが備えている別名機能や略語機能(同じものだ)が基本的だ:

  • alias
  • abbr
3.1.4.2 操作

Emacs 流キーバインドが既定。これで問題ない。

3.1.4.3 ファイル内容の管理

単純なテキスト編集のためだけにテキストエディターを起動するのは非効率的だ。リダイレクト、ヒアドキュメント、各種ツールを上手く使え。

3.1.4.4 長いファイルの参照
  • less, bat などのページャーを使え。
  • head, tail などを用いて必要部分のみを得ろ。
3.1.4.5 日付と時刻の扱い

コマンド date の書式を適切に指定すればファイル名の一部として利用可能だ。

3.2 使いやすいシェル

次世代の使いやすいシェルを使え。

3.2.1 fish シェル

3.2.1.1 基本的な使い方
  • 履歴管理不要
  • 自動補完
  • bash から鞍替えする人向けの FAQ がある。
3.2.1.2 設定
  • コマンド fish_config を実行するとブラウザーが開くらしい。
  • Oh My Posh のようなコマンドラインカスタマイズをコードで行っている。

3.2.2 Z シェル

An Introduction to the Z Shell を読めばいい。

3.2.3 他のモダンなシェル

  • Oil
  • murex
  • NuShell
  • PowerShell

3.2.4 どのシェルを使うべきか?

マッスルメモリ=無意識に操作できる程度に染みついている記憶

3.3 ターミナルマルチプレクサ

ターミナルに複数のウィンドウを重ねるツール。

3.3.1 screen

あまり使用するべきではない。

3.3.2 tmux

  • セッション、ウィンドウ、ペインなどの概念がある。
  • コマンドの一例を挙げると tmux new -s test でセッション test を起動する。
  • キーバインドとしては C-b wC-b z のような操作をする。

Windows Terminal のウィンドウでも tmux が使用可能であることを確認した。

3.3.3 他のマルチプレクサ

  • tmuxinator
  • Byobu
  • Zellij
  • dvtm
  • 3mux

3.3.4 どのマルチプレクサを使うべきか?

常用するかどうかは保留するが、tmux を使えるようになってはおきたい。

3.4 スクリプト

スクリプトは Bash コードを書くものとする。

3.4.1 スクリプトの基本

3.4.1.1 高度なデータ型
  • シェルの変数は文字列型であるのが基本だ。
  • 配列が使える。
  • 本書では言及していないが、連想配列が使える。
3.4.1.2 フロー制御

割愛。

3.4.1.3 関数

割愛。

3.4.1.4 高度な I/O

3.4.2 移植性の高い bash スクリプトの書き方

3.4.2.1 スクリプトの実行
  • 例の行は #! /usr/bin/env bash とする。仮想環境を念頭に置いているものと思われる。
  • スクリプトファイルに実行権限を付与するには chmod +x とする。厳密には chmod 750 のほうが良い。次章参照。
3.4.2.2 スケルトンテンプレート

次のフラグ設定を自作スクリプトに対して適用したい:

set -o errexit
set -o nounset
set -o pipefail

それぞれ、

  • エラーで停止する、
  • 未設定変数参照時にエラーとする、
  • パイプの一部での失敗を失敗扱いにする、

を指定する。

3.4.3 スクリプトの lint とテスト

  • ShellCheck
  • shfmt: 書式整形ツール
  • bats: Bash Automated Testing System; CI 構成用

3.4.4 GitHub のユーザ情報スクリプト

スクリプト gh-user-info.sh が手許にあるのが望ましい: https://github.com/mhausenblas/modern-linux.info/tree/main/code/ch03

3.5 まとめ

生産性と作業効率を上げるのがたいせつだ。

4 章 アクセス制御

4.1 基本

4.1.1 リソースと所有権

  • リソース:ユーザーが利用できるハードウェアやソフトウェア部品、言い換えるとファイルを指す。
  • 所有権:ファイルを作成したユーザーがその所有者となるのが通例だ。

4.1.2 サンドボックス化

FreeBSD jail, コンテナー、仮想マシンなどの手法がある。§4.4.2 や 9 章も見ろ。

4.1.3 アクセス制御の種類

アクセス制御は二種類に分類される:

  • 任意アクセス制御
  • 強制アクセス制御

SELinux は後者の実装例の一つだ。政府機関のような安全保障要件が厳格な環境で使用される。使い勝手が落ちるという難点がある。

4.2 ユーザ

ユーザーアカウントは Linux では二種類に分類される:

  • システムユーザー:デーモンと呼ばれるプログラムは、このユーザー権限でバックグラウンドプロセスとして実行される。
  • 一般ユーザー:人間に対応するユーザー。

ユーザー ID (UID) は 32 ビットの数値で表現される。

  • UID の値が 0 のユーザーは特別だ。これは root とか super user とか呼ばれる。何の制約もなく、あらゆる権限を有する。
  • UID の値が 1000 から当分までの値は通常ユーザー。
  • 自分の UID はコマンド id -u で見られる。

4.2.1 ローカルでのユーザ管理

ファイルで管理される。

ファイル /etc/passwd がユーザー名簿と考えられる。小さなデータベースのようだ。このファイルのレコードから次の情報を読める(右から左に?):

  • ログインシェル
  • ホームディレクトリー
  • GECOS フィールド(コメントのように用いられるようだ)
  • ユーザーの所属する最も代表的なグループの GID
  • UID
  • パスワード (x)
  • 名前

パスワードはファイル /etc/shadow に保存される。※暗号化されている。

ユーザーを追加するにはコマンド adduser を用いる。要特権。

グループという、一人以上のユーザーの集合を実体とする概念がある。

  • 普通のユーザーは一つの既定グループに属する(同時に他のグループに属してもかまわない)。
  • ファイル /etc/group がグループ名簿と考えられる。TODO: 読み方は?

4.2.2 ユーザの一元管理

この節の内容はプロ向け。

ユーザー管理が必要なマシンが複数あるなどの場合に、次のような方法を採る:

  • LDAP
  • ネットワーク経由 (Kerberos)
  • 設定管理システム (Ansible, Chef, Puppet, SaltState, etc.)

4.3 パーミッション

4.3.1 ファイルのパーミッション

権限は三種類:

  • ユーザー(所有者)
  • グループ
  • 上記以外

アクセスは三種類(ファイルとディレクトリーで意味あいが変わる):

  • r: read
  • w: write
  • x: execute

コマンド ls -l で対象ファイルのアクセスを、最初の列にある文字列として見られる:

$ ls -l /var/log/docker.log
-rw-r--r-- 1 root   docker 1691119 Jul 24  2024 /var/log/docker.log

この文字列はファイルタイプ+ファイルモードという構成だ。各文字の意味:

  • 最初の文字:ファイルタイプ。詳しくは info ls -n "What information is listed" を見るといい。例えば:
    • -: 通常ファイル
    • d: ディレクトリー
    • l: シンボリックリンク
  • 次の三文字:ファイル所有者のパーミッション
  • その次の三文字:ファイルのグループに属しているユーザーたちのパーミッション
  • 最後の三文字:それ以外のユーザーたちのパーミッション

パーミッションを八進数で表現することがよくある。例えば rw- は 6 だ。

※既定パーミッションは o666 や o777 から umask の値を引いた値となるようだ。

実行ファイルに setuid が付いていると、システムはプログラムを所有者権限で実行する。この挙動は root であるときに問題になる。

パーミッションを変更するコマンドは chmod, chown, chgrp だ。

4.3.2 プロセスの権限

プロセスは次の四種類の UID を用いる:

  • Real UID
    • プロセス起動者の UID を指す。
    • システムコール getuid(2) に対応。
    • コマンド stat -c "%u" /proc/$pid で値を見られる。
  • Effective UID
    • システムコール geteuid(2) に対応。
  • Saved set-user-ID
    • setuid が立っている場合に意味がある値。
    • システムコール getresuid(2) に対応。
  • File System UID
    • システムコール setfsuid(2) に対応。

後でこの記事を読みたい: linux - Difference between Real User ID, Effective User ID and Saved User ID - Stack Overflow

4.4 高度な権限管理

4.4.1 ケーパビリティ

  • 伝統的に root と関連付けられていた特権は、機能ごとに存在する capability に分解された。
  • スレッドごとに capability が存在する。
  • capability はシステムレベルのタスクにしか関係しない。
  • コマンド capsh --print はシステムに存在する capability 全てを見る。
  • コマンド grep Cap /proc/$$/status でコマンド発行元(この場合はシェル)の capability を見る。

4.4.2 seccomp プロファイル

プロセスが使用できるシステムコールを seccomp(2) で制限できる。

4.4.3 ACL

  • ACL はあるユーザーが所属するグループに入っていない(違う)ユーザーやグループに対して権限を与えられる。
  • コマンド grep -i acl /boot/config* の出力のどこかに POSIX_ACL=Y があれば、カーネルは ACL をサポートしている。

4.5 アクセス制御のよい実践方法

  1. 最小権限の原則。必要以上に大きい permission を与えない。必要に応じて sudo を使え。
  2. setuid を避けろ。代わりに capability を使え。
  3. 監査。ログを使えばいつ誰が何をしたかを検証できる。8 章を見ろ。

4.6 まとめ

  • capability や seccomp のような高度な機能はコンテナーと関係がある。
  • システムに存在するユーザーとファイルをつねに注視しておく必要がある。

5 章 ファイルシステム

  • UNIX の「すべてはファイルである」哲学を Linux は継承している。
  • ファイルシステムを統一されたインターフェイスと捉えるのが急所だ。

5.1 基本

  • 階層化
  • ディレクトリーと通常ファイル
  • コマンド ls, cd, pwd などでファイルシステムを探索する
  • パーミッション(前章を見ろ)
  • カーネルに実装されている

術語:ドライブ、パーティション、論理ボリューム、スーパーブロック、inode.

コマンドいろいろ:

  • lsblk --exclude 7: システムに存在するドライブ、パーティション、論理ボリュームを見る。
  • findmnt -D -t nosquashfs: ファイルシステム一覧を出力する。
  • stat $myfile: 個々のオブジェクトを見る。

表 5-1 の低水準コマンドを全部実行してみるといい。

Linux にはリンクが二種類ある:

  • ハードリンク
  • シンボリックリンク (ln -s)

5.2 仮想ファイルシステム

ファイル、ファイルシステムを操作するシステムコールと、操作に対応する処理を実装する個々のファイルシステムの間に挟まる層が VFS だという。

Linux カーネルが定義する VFS 関連データ構造:

  • inode
  • file
  • dentry
  • super_block
  • vfsmount
  • file_system_type
  • etc.

5.2.1 論理ボリュームマネージャ

  • PG, VG, LV をおぼえる。
  • ボリューム管理ツールは名前が統一されていて簡単に使える。
    • PG: lvmdiskscan, pvdisplay, pvcreate, pvscan.
    • VG: vgs, vgdisplay, vgcreate, vgextend.
    • LV: lvs, lvscan, lvcreate.

コマンド例:

sudo lvscan
sudo vgs
sudo pvdisplay

※手許の環境で実行しても何も出力されない。

5.2.2 ファイルシステムの操作

作成(フォーマット)とマウント(木に挿し込む)の二段階。

5.2.2.1 ファイルシステムの作成
mkfs -t ext4 /dev/some-vg/some-lv
5.2.2.2 ファイルシステムのマウント
  • 引数なし mount は一覧出力。
  • マウント時にはフォーマットタイプを明示する必要がある。
  • マウントを永続化するにはファイル /etc/fstab に記載する。

5.2.3 一般的なファイルシステムレイアウト

  • p. 93: ファイルシステムの作成、etc.
  • p. 95: man hier は自分の環境におけるファイルシステムツリーの構成を記述する。

5.3 擬似ファイルシステム

ファイルシステムのふりをして、通常の方法 (ls, cd, cat, etc.) でファイルシステムを操作できるようにしている。

5.3.1 procfs

元々の目的はカーネルからプロセス関連の情報を公開し、システムコマンドで使用できるようにすることだった。

  • cat /proc/self/status はこの cat プロセスに関するプロセス状態を出力する。
  • cat /proc/self/net/arp は同じく ARP 情報を出力する。

procfs は低レイヤーのデバッグや、システムツールの開発をしているとたいへん便利だ。

5.3.2 sysfs

sysfs は /sys と対応。

コマンド ls -al /sys/block/sda はブロックデバイス sda の情報を示すファイル一覧を表示する。

5.3.3 devfs

devfs は /dev と対応。ブロックデバイス、キャラクターデバイス、特殊デバイスを管理できる。 /dev/null, /dev/random, /dev/tty などでおなじみ。

5.4 通常のファイル

5.4.1 一般的なファイルシステム

カタログ的内容につき割愛。

5.4.2 インメモリファイルシステム

カタログ的内容につき割愛。

5.4.3 コピーオンライトファイルシステム

高速 I/O と少ないディスク使用量を両立する。CoW の原理は C++ の文字列実装で学んだものと同様のようだ。

5.5 まとめ

何を学びたい?

6 章 アプリケーション、パッケージ管理、コンテナ

この章のコードはすべて https://github.com/mhausenblas/modern-linux.info/tree/main/code/ch06/greeter にある。必要に応じて手許にダウンロードしろ。スクリプトは chmod 750 しておけ。

6.1 基本

《アプリを完全に理解するために必要な前提知識(略)をここまでに説明したことで、ようやくアプリに取り組める状態になった》 そうだ。

本章で頻出する術語:

  • プログラム:実行ファイルと考えてよいようだ。
  • プロセス:メインメモリーにロード済みの実行中プログラムを指す。
  • デーモン:サービスをも呼ばれる。バックグラウンドプロセスであることが必要。
  • ブート:ハードウェア、OS の初期化を行い、Linux を利用可能状態に至らせるための Linux による一連の手順。

6.2 Linux の起動プロセス

次の五段階に分解して考える:

  1. UEFI or BIOS
  2. boot loader
  3. kernel
  4. Init
  5. 他のユーザー空間(シェルなどの初期化?)

カーネルは圧縮されて /boot に保存されている。コマンド ls で確認しても何もないようだが。

init システム。PID 1 のバックグラウンドプロセス。プロセス階層の根。

$ ps u 1
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.0  0.0   2476  1712 hvc0     Sl+  Aug19   0:00 /init

6.3 systemd

  • 元々は initd に置き換わる init システムだったが、時代が進むにつれて機能がいろいろと追加した。
  • systemd は依存関係が解決済みのサービスを並列で起動できる。このため起動時間が短縮できる。

6.3.1 ユニット

systemd を機能や資源により、論理的なまとまりに分解するとこうなる:

unit description
service サービス、アプリケーションを管理
target 依存関係
mount mount positions
timer cron ジョブなどのタイマー
socket ネットワーク、プロセス間通信ソケット
device udev, sysfs が用いる
automount 名前通り
swap 名前通り
path ファイルやパス監視によるサービス起動
swapshot システム再構築
slice cgroup 関連(後述)
scope 外部が作成したシステムプロセスの集合

ユニットを systemd に認識させるには、ファイルとして配置する必要がある。サーチパスは複数あるようだ。

6.3.2 systemctl による管理

systemctl 以外にも systemd を操作するツールがある。

6.3.3 journalctl による監視

journalctlsystemd が管理するログを閲覧するツールだ。

6.3.4 greeter のスケジューリング例

シェルスクリプト greeter.sh を一時間おきに起動する構成を実習。これはぜひ実施しよう。物資は上記リンクにある。

  1. 本書の内容でファイル greeter.{sh,service,timer} を作り、ひとまず任意のディレクトリーに置いてよい。
  2. 両者を /run/systemd/system に置く。コマンド sudo cp で構わないようだ。
  3. コマンド systemctl status greeter.timer を実行して確認する。
  4. ログを見るには journalctl -f -u greeter.service を実行する。

この貧弱なメモを実際に試したところ、考慮がやはり足らなかった:

  • ファイル greeter.service 内にハードコードされたシェルスクリプトのパスは環境に合わせて修正しろ。
  • ファイル greeter.sh には permissions を適宜設定しろ。
  • サービスが inactive のままの場合、手動で sudo systemctl start してしまえ。気が済んだら stop しろ。

Ubuntu だと systemd は特段の設定なしで動作しているはずだが、WSL の場合はそうでないことがある。ファイル /etc/wsl.conf の内容を確認しろ。

[boot]
systemd=true

6.4 Linux アプリケーションのサプライチェーン

図 6-2 Linux アプリケーションのサプライチェーンと図 6-3 Linux のパッケージ管理とアプリケーションの依存関係の分類。よく出来ている。 特に、分類は次の三つになる:

  • 従来型
  • コンテナー
  • モダン

6.5 パッケージとパッケージマネージャ

この二つのコンビは Red Hat と Debian ベースのシステムから始まった。

6.5.1 RPM パッケージマネージャ

  • RPM の R は Red Hat を指す。PM は Package Manager の略。
  • フォーマットは .rpm であり、ソースとバイナリーのどちらもアリ。

本書では yum を使った例を示している。すべて root で実行する(実践的には sudo を用いる):

yum search golang
yum install golang
yum info golang

6.5.2 Debian deb

Debian で開発されたパッケージマネジャー。

使いやすいラッパーがいろいろとある。私は apt を用いる。これも root で実行するツールだ:

apt search curl
apt install curl
apt show curl

6.5.3 言語固有のパッケージマネージャ

プログラミング言語のそれぞれがパッケージマネジャーを独自に用意している。C/C++ ですら存在するのか。

  • C/C++ は《Conan や vcpkg が最適だとされている》らしい。
  • Go は言語にパッケージ管理が組み込まれている。例えば go mod などのコマンドがある。
  • Node.js npm が有名。
  • Java: maven, nuts, etc.
  • Python: PyPM は聞いたことがない。
  • Ruby: RubyGems (gem), Rails.
  • Rust: Cargo (cargo)

6.6 コンテナ

コンテナーとはプロセスのグループであり、Linux の namespace, cgroup, オプションで CoW ファイルシステムを利用してアプリケーションレベルの依存関係の管理を行うものだ。

  • 用途は多岐にわたる。
  • 著名なコンテナーに Docker が挙げられる。

OCI 準拠のコンテナーを議論する。

6.6.1 namespace

プロセスごとにファイルシステム、ネットワーク、ユーザー等の見え方を変更できるような機能だ。

syscall description
clone(2) 子プロセスを作成する
unshare(2) 現在他のプロセスと共有されている実行コンテキストの一部をプロセスから切り離す
setns(2) スレッドを別の namespace に関連付け直す

システムで使用されている namespace を表示する:

$ sudo lsns
        NS TYPE   NPROCS PID USER COMMAND
4026531834 time       26   1 root /init
4026531835 cgroup     26   1 root /init
4026531837 user       26   1 root /init
4026531840 net        26   1 root /init
4026532240 ipc        26   1 root /init
4026532251 mnt        26   1 root /init
4026532252 uts        26   1 root /init
4026532253 pid        26   1 root /init

6.6.2 cgroup

  • 資源の使用を制限するためのもの。
  • v1 と v2 の二バージョンある。
6.6.2.1 cgroup v1

割愛。

6.6.2.2 cgroup v2
  • cgroup v2 には一つの階層しかない。コントローラーすべてが同じ方法で管理する。
  • コマンド systemctl status で Linux システムの cgroup v2 の木全部を表示できる。
  • コマンド systemd-cgtop で資源使用状況を確認可能(※対話的でない)。

6.6.3 コピーオンライトファイルシステム

  • §5.4.3 を見ろ。
  • CoW はビルド時に、パッケージを自己完結した単一ファイルにするのに使用する。

6.6.4 Docker

ここから Docker 実習。コンテナーに greeter.sh を入れて実行するものだ:

  1. ファイル Dockerfile を作る。
  2. イメージを作る。docker build
  3. イメージを見る。docker images
  4. イメージを実行する。docker run
6.6.4.1 コンテナイメージ

ファイル Dockerfile を作る。内容は先述のリンク先にもある。

6.6.4.2 コンテナの実行

Docker はコマンド docker run の引数を基に、必要な namespace と cgroup を作成し、イメージ定義のアプリケーションを起動する。

6.6.4.3 例:コンテナでの greeter
  1. ファイル Dockerfile を作る。
  2. イメージを作る。sudo docker build -t greeter:1
  3. イメージを見る。sudo docker images
  4. イメージを実行する。sudo docker run greeter:1

6.6.5 他のコンテナ関連のツール

割愛。

6.7 モダンなパッケージマネージャ

  • Snap
  • Flatpak
  • AppImage
  • Homebrew

※Flatpak は Ubuntu でも利用可能。Homebrew は便利で使っている。

6.8 まとめ

スタータップ、パッケージ管理、コンテナー。

7 章 ネットワーク

7.1 基本

図 7-1 Linux ネットワークの概要:前述の区分どおり、三層に分けて構成要素をまとめてある。下層から上層に向かって順に:

  • ハードウェア:NIC, ワイヤレス
  • カーネル
    • ドライバー
    • IP, ICMP
    • TCP, UDP
    • ソケット
  • ユーザー空間:各種アプリケーション(ブラウザー、メール、等々)

7.2 TCP/IP スタック

図 7-2 通信における TCP/IP 層の連携。ここは四層に分けて考える。下層から上層に向かって順に:

役割
リンク層 物理デバイス間でのパケット通信を行う。
インターネット層 ネットワークによるマシン間のパケット通信を行う。
トランスポート層 パケットの転送方法、ポートによるマシン上のサービスの認識、データの完成性の確認を行う。
アプリケーション層 ユーザー向けのツールやアプリケーションを扱う。

7.2.1 リンク層

関連用語:

  • イーサネット
  • ワイヤレス (Wi-Fi)
  • MAC アドレス
  • インターフェイス
7.2.1.1 NIC

NIC (Network Interface Controller) は必須のハードウェアだ。カードだ。

  • 物理的接続。
  • モダンではないようだが、コマンド ifconfig がわかりやすい。
    • カードの情報を得る。
    • 説明のしやすさのためだけに使う。
  • 最近はコマンド ip を使う。
  • どちらの出力にも現れる UPRUNNING などのフラグの意味を知るには、 man 7 netdevice を見ろ。

WSL 環境で実行したところ、lo および eth0 が示された。

$ ip link show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP mode DEFAULT group default qlen 1000
    link/ether 00:15:5d:af:9e:31 brd ff:ff:ff:ff:ff:ff
7.2.1.2 ARP

ARP (Address Resolution Protocol) は MAC アドレスを IP アドレスに写像する。つまり リンク層からインターネット層への対応を得る。

コマンド arp または ip neigh を実行するとこういう出力が得られる:

$ ip neigh
172.21.0.1 dev eth0 lladdr 00:15:5d:7a:cc:0c REACHABLE

コマンド iw はワイヤレスデバイスを扱う。

  • iw dev wlp1s0 info: 基本情報を出力する
  • iw dev wlp1s0 link: 接続情報を出力する

TODO: WSL で実行すると nl80211 not found. とエラーで終了すると思う。

7.2.2 インターネット層

  • この層ではパケットすべてを独立したものをみなす。
  • この層では IP を扱っている。マシンを論理的に見分けるプロトコルだ。
  • IP には IPv4 と IPv6 の二種類が存在する。
7.2.2.1 IPv4

IPv4 アドレスは 32 ビット値だ。63.32.106.149 のように 8 ビットずつ四つに分けて記す。

図 7-3 RFC 791 で定義されている IP ヘッダーフォーマットはオリジナル仕様書でアスキーアートで表現されている。

CIDR (Classless Inter-Domain Routing) は IP アドレスを一つではなく、アドレス範囲を表す。開発者試験で出題されがちなアレだ。 CIDR から具体的な範囲を示してくれるツールがいくつもある。それらを利用すればいい。

特別な目的で予約済みの IP アドレスというのがある: Reserved IP addresses - Wikipedia

アドレス範囲 役割
127.0.0.0/8 ローカルホストのための予約済みアドレス
169.254.0.0/16 リンクローカルアドレス
224.0.0.0/4 マルチキャストのための予約済みアドレス

プライベート IP: 公共のインターネット上で通じない IP アドレス。LAN 上で使用される IP アドレスとして用いられる。

  • 10.0.0.0/8
  • 172.16.0.0/12
  • 192.168.0.0/16

0.0.0.0 も特別。意味は状況によって異なると覚えておくのが無難だろう。

コマンド ip addr show は IP アドレス一覧を出力する。inet から始まる行に注目:

$ ip addr show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 00:15:5d:af:9e:31 brd ff:ff:ff:ff:ff:ff
    inet 172.21.15.53/20 brd 172.21.15.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::215:5dff:feaf:9e31/64 scope link
       valid_lft forever preferred_lft forever
  • inet 127.0.0.1/8 のほうがループバックインターフェイスの IP アドレス。
  • inet 172.21.15.53/20 のほうがワイヤレス NIC のプライベート IP アドレス。
7.2.2.2 IPv6
  • IPv6 アドレスは 128 ビット値。16 ビット値をコロンで区切って八つ並べる。十六進数表記で。
  • 独特の略記法がある。
  • IPv4 との互換性はない。
7.2.2.3 ICMP
  • RFC 792
  • Internet Control Message Protocol.
  • とりあえず ping のプロトコルだと覚えておけばいいだろう。
  • gping という、端末にグラフィカルな表示をするツールがある。
  • IPv6 に対する pingping6 を使え。

TODO: WSL 環境では IPv6 を使用可能にするのに別途構成が必要らしい。

7.2.2.4 ルーティング

経路選択処理。システムに届いた個々のパケットをどこに送るかを決める。関連する機能には iptables がある。

  • sudo route -n: 選択経路情報を出力する。
  • sudo ip route: 同じく。
  • traceroute: ネットワークインターフェイスの接続性を出力する。

最後のツールは動作が怪しい。米印はタイムアウトだと考えられる:

$ traceroute www.example.com
traceroute to a1422.dscr.akamai.net (23.52.168.19), 64 hops max
  1   172.21.0.1  0.470ms  0.353ms  0.311ms
  2   192.168.3.1  2.152ms  1.224ms  1.368ms
  3   *  *  *
  4   221.110.214.241  72.311ms  37.983ms  17.408ms
  5   221.110.184.26  20.526ms  19.411ms  20.473ms
  6   *  *  *
  7   *  *  *
  8   *  *  *
  9   *  *  *
 10   *  *  *
 11   *  *  *
 12   *  *  *
 13   23.52.168.19  17.630ms  *  51.635ms

BGP (Border Gateway Protocol): 知っていることがひじょうに重要とまで言っている。自律システム?

7.2.3 トランスポート層

7.2.3.1 ポート

ポートは 16 ビット値であり、ある IP アドレスで利用するサービスを識別する。例えば 22 と 80 はそれぞれ SSH と HTTP だ。

ファイル /etc/services にポートとプロトコルの対応が記されている。手許のそれを見たら三百数十行のテキストファイルだった。

コマンド nmap -A localhost でローカルマシンのポートを調べる。

  • STATE が open なポートを示す。
  • このコマンドを他のマシンに対して実行してはいけないことになっている。
7.2.3.2 TCP
  • Transmission Control Protocol.
  • セッションベースのプロトコルであり、パケットの順序性を保証する。エラーが発生すると再送。
  • 図 7-5 RFC 793 で定義された TCP ヘッダフォーマットは、オリジナル仕様書では例によってアスキーアートで表現されている。
  • TCP 通信は傍受可能、つまりパケットを「捕まえる」ことができ、それを覗くことが可能だ。
7.2.3.3 UDP
  • User Datagram Protocol.
  • データグラムという形態のメッセージを送信する。
  • 図 7-6 RFC 768 で定義された UDP ヘッダフォーマット。データ長は不定のようだ。 これを見てわかるように、これまでのプロトコルヘッダフォーマットと比較してひどく単純だ。
  • 《オーバーヘッドが非常に少なく、高いスループットを実現できる》。
  • 詳しくは man 7 udp を見ろ。

7.2.4 ソケット

  • コマンド ss -s はシステムで使用される TCP ソケット一覧を出力する。
  • コマンド ss -udp はその UDP 版。
  • コマンド lsof -c chrome -i udp を実行すると、Chrome が使っている UDP ソケットの情報を出力する。

7.3 DNS

DNS (Domain Name System) はインターネット上のドメイン名と IP アドレスを対応させ る制度だ。

  • IP アドレスは変更する可能性がある。
  • ローカルファイル /etc/hosts に IP アドレスとホスト名の対応を手動で記せる。 システムが外部の DNS サーバーに問い合わせる前にこのファイルの内容が照合される。
  • ドメイン名を階層的に命名する。

術語:

  • FQDN: Fully Qualified Domain Name
  • ネームサーバー:DNS サーバーの一種。ドメイン名を IP アドレスに変換する。
  • リゾルバー

図 7-7 DNS の構成。RFC 1035 p. 6 のアスキーアートに基づくと思われる。

  • DNS のルートサーバーは 13 個ある。
  • ルート直下にトップレベルドメイン (TLD) がある。FQDN でいえば最後の部分。
    • gTLD: e.g. .org, .com
    • ccTLD: e.g. .jp
    • sTLD: e.g. .aero, .gov

7.3.1 DNS レコード

ネームサーバーはレコードを管理する。

  • レコードは型、ペイロード、TTL, 等々のフィールドからなる。
  • レコードの種類はたくさんある。A, AAAA, CNAME, NS, PTR, SRV, TXT, etc.
  • レコードはゾーンファイルと呼ばれるファイルにテキスト形式で表現される。
  • ネームサーバーがゾーンファイルを読み込んでデータベースを構築する。

TODO: ここの理解が怪しい。

TODO: p. 157 のコードを模式化すると《図 7-8 ドメイン名空間と FQDN の例》になる?

著者のゾーンには著者がサブドメインを自由に作成可能。それにはゾーンの DNS 設定を更新すればよい。

7.3.2 DNS ルックアップ

コマンド host はローカル名、グローバル名の IP アドレス解決を行う。

  • コマンド host -a localhost はローカル IP アドレスを示す。
  • コマンド host mhausenblas.info は著者のドメインの FQDN を示す(実行すると四つ出力された)。
  • コマンド host 185.199.110.153 で逆引きと呼ばれる操作をする:
$ host 185.199.110.153
153.110.199.185.in-addr.arpa domain name pointer cdn-185-199-110-153.github.com.

コマンド dig は DNS レコードを調べる。ANSWER SECTION は DNS の A レコードだ。

$ dig mhausenblas.info

; <<>> DiG 9.18.30-0ubuntu0.24.04.2-Ubuntu <<>> mhausenblas.info
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 28684
;; flags: qr rd ad; QUERY: 1, ANSWER: 4, AUTHORITY: 0, ADDITIONAL: 0
;; WARNING: recursion requested but not available

;; QUESTION SECTION:
;mhausenblas.info.              IN      A

;; ANSWER SECTION:
mhausenblas.info.       0       IN      A       185.199.109.153
mhausenblas.info.       0       IN      A       185.199.111.153
mhausenblas.info.       0       IN      A       185.199.108.153
mhausenblas.info.       0       IN      A       185.199.110.153

;; Query time: 0 msec
;; SERVER: 172.21.0.1#53(172.21.0.1) (UDP)
;; WHEN: Sun Aug 24 22:05:10 JST 2025
;; MSG SIZE  rcvd: 114

TODO: AUTHORITY SECTION が現れない理由は?

TODO: SRV レコードの話がわからない。

7.4 アプリケーション層ネットワーク

ユーザー空間がアプリケーション層に丸ごと対応すると考えてよい?

7.4.1 ウェブ

  • URL: RFC 1738 で規定
  • HTTP: 次の三つが重要
    • メソッド
    • 命名規則
    • ステータスコード
      • 200 台は成功
      • 300 台はリダイレクト
      • 400 台はクライアントエラー
      • 500 台はサーバーエラー
  • HTML

URL の構成は RFC 3986 で規定されている。

foo://example.com:8042/over/there?name=ferret#nose
   \_/   \______________/\_________/ \_________/ \__/
    |           |            |            |        |
 scheme     authority       path        query   fragment
    |   _____________________|__
   / \ /                        \
   urn:example:animal:ferret:nose
  • scheme が http の場合には authority はホスト名、コロン、ポート番号となる。

HTTP サーバーの起動方法:

  • 別窓で起動コマンドを実行するのを前提とする。
  • python -m http.server で作業ディレクトリーの内容を公開する。簡易サーバー。
  • docker run --name mywebserver --rm -d -v "$PWD:/usr/share/nginx/html:ro -p 8042:80 nginx:1.21 のように、まともな HTTP サーバーを起動するのもあり。
  • 別窓で curl localhost:8000 のようにしてアクセスして確認できる。

表 7-1 curl の便利なオプションは著者厳選(オプション -I, -k はヘルプで見た覚えがない)。

wget も良いが curl より制限があるという。

7.4.2 SSH

SSH は Telnet の安全版と考えられる。後者は通信を暗号化しない。

本書ではクラウド上の仮想マシンへログインする例を示している。真似したいが、次の前提を整えられる環境がない:

  • IP アドレスとデフォルトのユーザー名がわかっている
  • 秘密鍵ファイルを作成済み

7.4.3 ファイル転送

  • SCP (Secure Copy Protocol): SSH に基づくファイル転送通信規約。
  • rsyncscp より良い。これも SSH を使う。
  • 転送の宛先は user@host: 形式で指定する特徴が共通している。
  • FTP はもう使わないほうがいい。
  • AWS は知らない。

7.4.4 NFS

  • NFS: Network File System
  • AWS, Azure など、クラウドプロバイダーが NFS を serve していることが多い。

7.4.5 Windows とのファイル共有

  • SMB (Serve Message Block) や CIFS を使用する。
  • Linux とファイル共有をするならば、標準の Samba を用いることになるだろう。

7.5 ネットワークの高度なトピック

開発者、システム管理者ならば存在は知っておく。

7.5.1 whois

コマンド whois(1) はドメイン名または IP アドレスの所有者、登録者情報を見る。

whois ietf.org のように使う。出力が長い。

7.5.2 DHCP

  • DHCP は IP アドレスをホストへ自動的に割り当てるネットワークプロトコルだ。
  • コマンド dhcpdump を使えば DHCP パケットをスキャンできる。 E.g. sudo dhcpdump -i $interface_name

7.5.3 NTP

割愛。

7.5.4 wiresharktshark

CLI なら tshark, GUI なら wireshark: 低レベルのネットワークトラフィック解析ツール、パケット表示ツール。

  • E.g. sudo tshark -i $interface_name tcp
  • tcpdump のほうが古い。

TODO: インストールして使ってみる。

7.5.5 他の高度なツール

名前だけ挙げると socat, geoiplookup(1), Inlets, BitTorrent. まだ早い。

7.6 まとめ

  • TCP/IP
  • DNS
  • アプリケーション層と高度なネットワーク

8 章 オブザーバビリティ(可観測性)

本章を読むことで次のことができるようになることを目的とする:

  • プロセスのメモリー消費を把握する
  • ディスク領域がどれくらい不足するかを予測する
  • カスタムイベントの警報を知る(セキュリティー)

観測可能性は事後的であることが通例だが、予測のための観測もある。

図 8-1 は Linux Performance からの引用(英語のほうが見易い)。

8.1 基本

8.1.1 オブザーバビリティの戦略

TODO: OODA ループ戦略とやらをよく調べる。最初の O が Observe から来ている。

8.1.2 用語

  • 観測可能性は見るだけでなく、それから何らかの行動をするということが目的。例:システムの反応が遅い→あるプロセスがメモリーを食いまくっている→殺してみると状況が改善した。
  • シグナルの発生源は Linux またはアプリケーションだ。
  • 宛先
  • テレメトリー

8.1.3 シグナルの種類

  • ログ
  • メトリクス
  • トレース
8.1.3.1 ログ
  • すべてのシステムが生成する基本シグナル
  • 人間が扱う
  • 構文解析が容易であるテキスト形式
  • タイムスタンプが付随する
8.1.3.2 メトリクス
  • メトリクスとは定期的に測定した数値データ(=時系列)を意味する。
  • 用途は集計やプロットなど。

メトリクスは次に分類される:

  • カウンター:増えるだけのデータ。処理数などを表現する。
  • ゲージ:増減するデータ。現在のメモリーサイズ、実行中プロセス数などを表現する。
  • ヒストグラム:分布。
8.1.3.3 トレース
  • 実行時の情報を動的に収集するもの。
  • 用途はデバッグなど。性能評価にも用いられる(§8.4.1 を見ろ)。

8.2 ログ

表 8-1 一般的なログフォーマット。五種類ある。

  • ログにおいてはオーバヘッド(負荷)は避けたい。
  • ログ負荷を抑えるツールに logrotate(8) がある(ログファイルを片付けるツール)。
  • ログには DEBUG や INFO などのログレベルという、ログメッセージを度合いで抽出するのに用いられる値を持つことが多い。

自分の環境で ls -al /var/log を実行してみる。

  • auth.log: ログイン情報
  • btmp: ログイン失敗
  • lastlog: ユーザー全員の最終ログインログ
    • コマンド lastlog を実行するといい。
  • syslog: syslogd の場所(?)

コマンド tail -f $logfile が基本的だ。リアルタイムでログを確認できる。

8.2.1 Syslog

  • RFC 5424 でフォーマットが定義されている。
  • ヘッダーフィールド?
  • syslogd を使ってログを管理するのが一般的だ。次のような新しい実装もある:
    • syslog-ng
    • rsyslog

8.2.2 journalctl

§6.3 も見ろ。

  • ログをバイナリーで保存する。すなわち tail, cat, grep などの便利ツールが使えない。
  • 引数なしで journalctl を実行するとページャーが起動する。
  • 時刻や時間を指定して実行すると、対応するログが閲覧できる。例:
    • journalctl --since "3 hours ago"
    • journalctl --since "2021-09-26 15:30:00" --until "2021-09-26 18:30:00
  • journalctl -u appname.service でサービス appname のログを閲覧する。
  • 出力書式はオプション -o で指定する。他には書式完全カスタマイズも可能。
  • journal -ftail -f の対応物。別窓で実行したい。

手許の環境で試したら、べらぼうに古いログしか閲覧できない。おそらく関連サービスを無効にしている。

8.3 監視

監視:システムやアプリケーションのメトリクスを収集するの意。

手法:

  • メトリクスを時系列で追跡する
  • 指定の条件下で警報を出すように仕掛ける

コマンド uptime はシステムの稼働時間とロード平均を出力する。ロード平均という概念と末尾三つの項目の読み方は知らないとわからないので man 1 uptime で覚えろ。

$ uptime
 22:14:36 up 15:49,  0 user,  load average: 0.02, 0.10, 0.08

コマンド free -h は RAM 消費量を出力する。

$ free -h
               total        used        free      shared  buff/cache   available
Mem:           3.8Gi       865Mi       2.9Gi       2.7Mi       262Mi       3.0Gi
Swap:          2.0Gi          0B       2.0Gi

コマンド vmstat 1 は RAM の stats を出力し、一秒ごとに更新する。

$ vmstat 1
procs -----------memory---------- ---swap-- -----io---- -system-- -------cpu-------
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st gu
 0  0      0 3072000  23240 247388    0    0    34     7  105    0  1  0 99  0  0  0
 0  0      0 3074208  23240 247388    0    0     0     0   18   78  0  0 100  0  0  0
 0  0      0 3074208  23248 247388    0    0     0    14   21   90  0  0 100  0  0  0
 0  0      0 3074208  23248 247388    0    0     0     0   14   63  0  0 100  0  0  0
 0  0      0 3074208  23256 247388    0    0     0     6   25  102  0  0 100  0  0  0
 0  0      0 3074208  23256 247388    0    0     0     0   14   68  0  0 100  0  0  0
^C

コマンド time は指定コマンドを実行し、システム資源使用を概観する。

$ time (\ls -R /etc 2&>/dev/null)

real    0m0.123s
user    0m0.001s
sys     0m0.019s
  • real にはあまり意味がないという。
  • usersys がそれぞれユーザー空間とカーネル空間における CPU 時間であることを憶えておけばいい。

8.3.1 I/O デバイスとネットワークインタフェース

コマンド iostat -z --human は I/O デバイスメトリクスの概要を示す:

$ iostat -z --human
Linux 5.15.153.1-microsoft-standard-WSL2 (NOTEPC-96LE0LS)       08/25/25        _x86_64_        (4 CPU)

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
           0.5%    0.0%    0.3%    0.1%    0.0%   99.1%

Device             tps    kB_read/s    kB_wrtn/s    kB_dscd/s    kB_read    kB_wrtn    kB_dscd
sda               0.03         1.7k         0.0k         0.0k      93.5M       0.0k       0.0k
sdb               0.00         0.0k         0.0k         0.0k       1.2M       4.0k       0.0k
sdc               1.32        34.0k         7.3k         7.3k       1.9G     413.6M     410.4M
  • tps 欄は一秒あたりの転送量
  • read, wrtn はデータ量

コマンド ss -atup は TCP と UDP の両方のソケットと、それを使っているプロセスを出力することが可能だ。 コマンド netstat のほうが古い。

$ ss -atup
Netid State  Recv-Q Send-Q Local Address:Port  Peer Address:Port  Process
udp   UNCONN 0      0          127.0.0.1:323        0.0.0.0:*
udp   UNCONN 0      0              [::1]:323           [::]:*
tcp   LISTEN 0      511        127.0.0.1:38303      0.0.0.0:*      users:(("node",pid=21871,fd=20))
tcp   ESTAB  0      0          127.0.0.1:52574    127.0.0.1:38303  users:(("node",pid=8367,fd=21))
tcp   ESTAB  0      0          127.0.0.1:38303    127.0.0.1:52574  users:(("node",pid=21871,fd=23))
tcp   ESTAB  0      0          127.0.0.1:38303    127.0.0.1:52580  users:(("node",pid=22109,fd=22))
tcp   ESTAB  0      0          127.0.0.1:52580    127.0.0.1:38303  users:(("node",pid=8376,fd=21))

コマンド sudo lsof -i TCP:1-1024 はネットワーク接続の情報を well-known ports のみ出力する。 PID がわかっている場合には lsof -p $pid とできる。

性能監視ツールは他にも sar(1), perf などがある。

8.3.2 統合パフォーマンス監視

※この辺から読み流している。

  • top(1): ヘッダーに概要表示。uptime(1) と同じ情報。CPU, RAM 詳細は表形式。プロセス一覧……。
    • Windows におけるタスクマネジャーだろう。
    • キーバインドを習得する必要アリ。
    • 類似物:htop(1), atop, below (cgroup v2)
  • その他
    • Glances
    • Guider: 少し調べたところ Python 製らしい?
    • neoss
    • MTR

8.3.3 インスツルメンテーション

  • どうやって自分で実装するか?
    • 自動:開発者がコードを追加する必要がない
    • カスタム:メトリクス出力コード片を手動で入れる
  • StatsD
  • その他、プルベース、スクレイピング

8.4 高度なオブザーバビリティ

8.4.1 トレースとプロファイリング

  • プロセスの実行を時系列に沿ってキャプチャーすること。
  • トレースの情報源は Linux カーネル、ユーザー空間を利用する。
  • トレースの使用例
    • strace などを使ったデバッグ
    • perf を用いたフロントエンドでの性能解析

図 8-5 perf top のスクリーンショット。実行に sudo が要る。

  • ePBF が今後のカスタムトレースの主流になるだろう。
  • プロファイルングはトレースの特殊な例だ。
  • pprof(1), Valgrind, flame graph visualizer などのプロファイリングツールがある。

図 8-6 継続的プロファイリングツール parca のスクリーンショット。非常に参考になる例と述べている。

8.4.2 Prometheus と Grafana

この両者を組み合わせ、長時間メトリクスから高度な observility が得られる。

TOOD: 構成が面倒なのは明らかゆえ、試すのは他を全部やってから最後にする。

8.5 まとめ

  • 基本
  • ログ
  • 監視
  • 高度なトピック

9 章 高度なトピック

9.1 プロセス間通信

IPC があるのは、プロセスが通信し、それぞれの処理を同期し、データを共有するためだ。

9.1.1 シグナル

  • シグナルはプロセスに送られる非同期通知だと考えられる。
  • シグナル一覧を確認するには man 7 signal を見る。
  • シグナルのほとんどに対してカスタムハンドラーを定義できる。

表 9-1 一般的なシグナルは七個。SIGQUIT を Ctrl+\ で発生するのは知らなんだ。

コマンド kill はプロセスにシグナルを送るものだ(殺すだけではなかった)。

コマンド kill $pidkill $pid SIGTERM と同値。

シグナルハンドラーの設定には trap を用いる。

9.1.2 名前付きパイプ

名前付きパイプは pipefs 疑似ファイルシステムを用いて実現するものだ。

$ mkfifo examplepipe
$ ls -l examplepipe
prw-r--r-- 1 user user 0 Aug 26 23:14 examplepipe
$ while true ; do echo x > examplepipe ; sleep 5 ; done &
[1] 29616
$ while true ; do cat < examplepipe ; sleep 5 ; done &
[2] 29666
x
x
...

9.1.3 UNIX ドメインソケット

  • UNIX ドメインソケットは名前付きパイプとは異なり双方向通信が可能。
  • ソケットは IP アドレスやポート番号ではなく、ファイルパスで指示する。
  • ドメインソケットはターミナルからというより、プログラムから使用するのが通例。

システムコール socket(2) の第二引数がソケットタイプ:

  • SOCK_STREAM
  • SOCK_DGRAM
  • SOCK_SEQPACKET

9.2 仮想マシン

図 9-1 仮想マシンのアーキテクチャ。

  • CPU にハードウェア仮想化と可視化機能があることが必要。
  • ホストカーネルは構成として KVM (kernel-based virtual machine) を含む。
  • 図式右側、四角が縦に積み重なっている。この部分が仮想マシンという理解でいいか?
  • VMM (virtual machine monitor) なる仮想デバイスを模倣するソフトウェア (e.g. QEMU, Firecracker) の上にゲストカーネル、ゲストプロセスが乗る。
  • ゲストカーネルは仮想マシン上で動作するカーネルの意。
  • ゲストプロセスはゲストカーネル上で稼働するプロセスの意。

ネイティブプロセスとゲストプロセスは分離されている。

9.2.1 KVM

一般的なハードウェアは仮想化に対応している。KVM を利用可能だ。次のコマンドで検査しろ:

grep 'svm\|vmx' /proc/cpuinfo

または

lsmod | grep kvm

※残念だが WSL Ubuntu では対応していないようだ。

9.2.2 Firecracker

  • Firecracker は Rust で書かれた VMM ソフト。
  • Firecracker は seccomp フィルターによって使用できるシステムコールを制限してりる。

9.3 モダンな Linux ディストリビューション

本書の定義によると《不変性と、自動アップグレード機構を前面に押し出したコンテナベースのディストリビューション》を指す。

9.3.1 Red Hat Enterprise Linux CoreOS

TODO: URL 確認

9.3.2 Flatcar Container Linux

https://www.flatcar.org/

9.3.3 Bottlerocket

https://github.com/bottlerocket-os/bottlerocket

9.3.4 RancherOS

https://rancher.com/docs/os/v1.x/en/

9.4 セキュリティに関するトピック

認証方式 authentication は authorizatin の前提条件。

9.4.1 Kerberos

RFC 4120 で規定されている何か。

図 9-2 Kerberos プロトコルの概念

9.4.2 PAM

  • PAM: Pluggable Authentication Modules
  • モジュール式
    • pam_localuser
    • pam_keyinit
    • pam_krb5

9.5 その他のモダン Linux の話、あるいは将来の話

執筆時点ではまだ主流になっていないだと?

9.5.1 NixOS

  • ソースベースの Linux ディストリビューション。
  • Nix パッケージマネジャーは OS 全体を構築する。
  • §5.2.3 のようなファイルシステムレイアウトを採用していない。

9.5.2 デスクトップ版 Linux

  • 最近は初心者向けのデスクトップ Linux ディストリビューションが多くある。
  • WSL を用いて Linux のグラフィカルアプリケーションを実行できる。

9.5.3 組み込みシステムにおける Linux

Raspberry Pi には Debian ベースの独自のディストリビューションが付属している。

9.5.4 クラウド IDE における Linux

  • Gitpod
  • GitHub の Codespaces

9.6 まとめ

  • IPC
  • 仮想マシン
  • モダンディストリビューション
  • セキュリティー
  • その他のモダンまたは将来の話題

付録 A 便利なコマンド集

包括的なコマンド集が欲しい場合は Linux Cookbook, 2nd Edition を用意する。

A.1 システム情報

Linux のバージョン、カーネル、CPU, RAM, ディスク、システムのハードウェア構成、メモリー消費量などを見るコマンド集。

パターン 1: 次のファイル群を直接閲覧する:

  • /etc/*-release: 手許の環境ではマッチするファイルは二つしかない。
    • /etc/lsb-release: Linux ディストリビューション情報。例えば Ubuntu であることがわかる。
    • /etc/os-release: OS 情報。Ubuntu ならば ID やバージョン、コードネームなどがわかる。
  • /proc/cpuinfo
  • /proc/diskstats: 読みづらい。
  • /proc/meminfo
  • /proc/version: 一行しかないので cat で十分だ。
$ cat /proc/version
Linux version 5.15.153.1-microsoft-standard-WSL2 (root@941d701f84f1) (gcc (GCC) 11.2.0, GNU ld (GNU Binutils) 2.37) #1 SMP Fri Mar 29 23:14:13 UTC 2024

パターン 2: 専用コマンドを用いる:

  • free -ht: オプション -t は RAM とスワップの和も表示する。
  • ulimit -n: 一度に開けるファイルの個数と考えてよい。
  • uname -a: システム情報全部を表示する。これも cat で見ればいい。

WSL で dmidecode を用いるコマンドに関しては、実行すると No SMBIOS nor DMI entry point found, sorry. で終了する。

A.2 ユーザとプロセス

ログインしているユーザー一覧はコマンド who または w で得る。

  • コマンド top -U $someone でユーザー $someone のプロセスにおけるシステムメトリクスを閲覧する。
  • コマンド ps faux でユーザー全員のプロセス全てを木形式で出力する。
  • コマンド ps -e | grep python で Python プロセスの ID を得る。オプション -e はプロセス全部の意。

プロセス ID を知ることで、当該プロセスへシグナルを送信可能になる。

訳者推奨の gstackpstack はユーザー空間でのスタックトレース表示ツールだそうだが、前者がパッケージ置き場に見つからない。 後者をインストールして適当なプロセス ID で実行すると (No symbols found) と出る。デバッグ用だそうだ。

A.3 ファイル情報

  • stat $some_file: ファイル $some_file のファイルシステムの情報まで含んだ詳細を出力する。
  • type $some_command: コマンド $some_command をシェルがどのように解釈するかを確かめる。
  • which $some_binary: コマンド $some_binary のパスを確かめる(本文中の記述も見ろ)。

コマンド stat 実行例:

$ stat /etc/locale.alias
  File: /etc/locale.alias
  Size: 2996            Blocks: 8          IO Block: 4096   regular file
Device: 8,32    Inode: 101250      Links: 1
Access: (0644/-rw-r--r--)  Uid: (    0/    root)   Gid: (    0/    root)
Access: 2025-08-27 01:53:43.296771588 +0900
Modify: 2024-08-08 23:47:42.000000000 +0900
Change: 2024-09-30 00:02:19.320088110 +0900
 Birth: 2024-09-30 00:02:16.750088122 +0900

コマンド type 実行例:

$ type history
history is a shell builtin
$ type ls
ls is aliased to `exa --header --time-style=long-iso --group-directories-first'
$ type exa
exa is hashed (/usr/bin/exa)
$ type cd
cd is a function
cd ()
{
    __zoxide_z "$@"
}

A.4 ファイルとディレクトリ

コマンド grep にオプション -H を明示的に指定するのは珍しい気がする。

コマンド dd で特定のサイズのファイルを生成できることを知っておく。次のコマンドは中身がオールゼロである 1 MB のファイルを生成する:

$ dd if=/dev/zero of=$output_path bs=1024 count=1000
1000+0 records in
1000+0 records out
1024000 bytes (1.0 MB, 1000 KiB) copied, 0.0039432 s, 260 MB/s

A.5 リダイレクトとパイプ

何回見ても忘れる &>2>&1 記法には困る。

本文中にあるように、パイプ内の終了コードを配列 PIPESTATUS で得られる:

$ ps -e | grep node | sort -k3
13017 pts/2    00:00:01 node
13042 pts/1    00:00:02 node
13265 pts/1    00:00:12 node
13026 pts/4    00:00:14 node
13004 pts/1    00:00:19 node
13227 pts/1    00:05:20 node
$ echo ${PIPESTATUS[@]}
0 0 0

A.6 時刻と日付

  • コマンド timedatectl status でローカル、UTC, 同期等の情報を得る。
  • コマンド date で ISO 8601 タイムスタンプを処理できることを覚えておく。

A.7 Git

  • git grep --color-moved は使ったことがない。オプション --color-words と併用できるか?
  • git rev-parse HEAD で最新コミットの SHA を得る。
  • git describe --tags --abbrev=0 で現在のブランチの最新タグの SHA を得る。

最後の二つは別名定義しておいても良いか。

A.8 システムパフォーマンス

訳者によると apt-get には -y オプションがあるが apt にはないとあるが、事実か?

コマンド yes nono を無限生成できる。

  • du -h $path: $path のディスク使用量を見る。
  • df -h ディスクの空き容量情報を含む一覧を表示する。
$ df -h
Filesystem      Size  Used Avail Use% Mounted on
none            2.0G  4.0K  2.0G   1% /mnt/wsl
drivers         456G  214G  243G  47% /usr/lib/wsl/drivers
none            2.0G     0  2.0G   0% /usr/lib/modules
none            2.0G     0  2.0G   0% /usr/lib/modules/5.15.153.1-microsoft-standard-WSL2
/dev/sdc       1007G   77G  880G   8% /
none            2.0G  224K  2.0G   1% /mnt/wslg
none            2.0G     0  2.0G   0% /usr/lib/wsl/lib
rootfs          2.0G  2.1M  2.0G   1% /init
none            2.0G  4.0K  2.0G   1% /run
none            2.0G     0  2.0G   0% /run/lock
none            2.0G     0  2.0G   0% /run/shm
none            2.0G     0  2.0G   0% /run/user
tmpfs           2.0G     0  2.0G   0% /sys/fs/cgroup
none            2.0G   76K  2.0G   1% /mnt/wslg/versions.txt
none            2.0G   76K  2.0G   1% /mnt/wslg/doc
C:\             456G  214G  243G  47% /mnt/c

付録 B モダン Linux ツール

本書で紹介しているこのページの一覧のほうが充実している。

以下、実際に試した寸評を記す。

※インストールのために Homebrew を使用可能にしておけ。

bat

batcat(1) の構文強調表示&ページャー付きツールとして使える。

  • 単純な cat(1) のほうが望ましい場合が多いゆえ、これを bat で置き換えるような alias を定義するには至らない。
  • ページャーが既定で動作するのはオプションでオフにできる。E.g. --pager=never
  • オプション -r を使えば出力する行範囲を指示することが可能。head(1) と tail(1) の代用になる。
  • よそのコマンドのヘルプを bat -plhelp にパイプすることでとても見やすくなる。

envsubst

今のところ利用する可能性が低いのでパス。

exa/eza

exa が紹介されているが現在は eza を用いる。これらのコマンドは ls(1) の現代的代替物となることを目的にしている。

これは alias などで ls を置き換えたい:

if [ -x "$(command -v exa)" ]; then
    alias ls='exa --header --time-style=long-iso --group-directories-first'
fi
  • オプション --icons でアイコン文字をファイル名の前に置く。
  • オプション -T/--tree でディレクトリー構造を木形式で出力する。
    • オプション --level= で深さを指定する。
  • オプション -l/--long の出力構成が異なる。
    • オリジナル同様、オプション --group-directories-first が使える。
    • オプション --git で Git 列を見せる。
    • オプション -h/--header でヘッダー行を付加する。表として見やすくなる。
    • オプション -o/--octal-permissions で Octal 列を見せる。そこでは 0755 のような文字列を見せる。
    • オプション --sort= でどの列でソートするのかを指示する。
    • オプション --timestyle= でタイムスタンプ書式を指定する。値は long-iso が いい。

dog

dogdig(1) の現代的代替コマンドだ。

どうもプロジェクトが現時点 (2025-09-03) で活動していないようだ。

fx

fx はターミナルのウィンドウで動作する JSON ビューワーだ。インストールしておいて損はない。

  • JSON ファイルを fx の引数に指定して実行すると専用ページャーが開く。専用キーバインドはオブジェクト閲覧操作を行う。
  • オブジェクトの加工出力機能も搭載している。
  • ささやかなカスタマイズならば環境変数設定により可能。

fzf

fzf は何かの一覧をターミナル画面で対話的に処理、特に選択するための UI と考えられる。 例えば ls, history, git branch, ps などの出力を fzf にパイプで与える用例がある。

  • 使いこなせると作業効率が飛躍的に上がる可能性が高い。
  • このツールの不思議な名前は fuzzy finder から着想されたらしい。そういえば項目のあいまい指定機能が独特だ。
  • Bash では C-r による履歴検索が楽になる。
  • かなり高級なカスタマイズが可能。

gping

gpingping(8) の出力がグラフ表示となるツールだ。

  • コマンドラインで gping $host を単に実行すればいい。
  • リアルタイムでプロット描画が更新される。

httpie

httpiecurl(1) や wget(1) の代替となる。

  • Python 環境が整っていればインストールは容易い。
  • インストールすることでコマンド httphttps が使用可能になる。
$ https www.example.com
HTTP/1.1 200 OK
Accept-Ranges: bytes
Alt-Svc: h3=":443"; ma=93600,h3-29=":443"; ma=93600
Cache-Control: max-age=948
Connection: keep-alive
Content-Encoding: gzip
Content-Length: 648
Content-Type: text/html
Date: Thu, 28 Aug 2025 13:53:03 GMT
ETag: "84238dfc8092e5d9c0dac8ef93371a07:1736799080.121134"
Last-Modified: Mon, 13 Jan 2025 20:11:20 GMT
Vary: Accept-Encoding

<!doctype html>
<html>
...略...
</html>

jo

jo は JSON コードを生成するツールだ。

  • インストールは apt install jo で動作するもので十分使える。
  • 例を見ても実践的な用途がわからない。便利でない可能性がある。

jq

本書を読む前にインストール済みだった。JSON コードを部分的に読み取るのに用いることが多い。

ripgrep (rg)

rggrep(1) の代替物。現代的であるだけでなく高速でもある。

  • grep(1) の引数 FILE 相当を与えないでも実行可能。作業ディレクトリー以下のファイルを再帰的に処理する。
  • 検索処理が無意味とわかっているファイル(例:バイナリーや .gitignore に指定されているファイル)を無視する。
  • grep(1) の --include/--exclude オプションよりも指定のしやすさで優る -g オプションが存在する。
  • -t/--type オプションで、例えば Rust 関係のファイルを処理 (e.g., -t rust) するように指示可能。
    • -T/--type-not オプションはその裏バージョン。
    • --type-list オプションで rg が対処可能な名前を一覧する。
    • --type-add オプションで --type などの名前を使用者が独自に拡張可能。
  • 構成ファイル支援あり。環境変数 RIPGREP_CONFIG_PATH でパスを指示する必要がある。
  • 前処理機能。--pre オプションで検索対象ファイルを前処理するスクリプトなどを指定することが可能。

sysz

syszsystemctl(1) の操作を上述の fzf で行うようにするものだ。

  • 先に fzf を動作可能状態にしておく必要がある。
  • systemctl(1) を多用する人ならば有用であると考えられる。そうでない人はこのツールと同時に学習するのもいい。おそらく systemd(1) とも。

tldr

tldr はコマンドレシピ集だと考えられる。引数にコマンド名を単純に指定して実行すると、よく使われるコマンドラインの用例を示すツールだ。

インストールしておいて損はない。

$ tldr hostnamectl

  hostnamectl

  Get or set the hostname of the computer.
  More information: https://manned.org/hostnamectl.

  Get the hostname of the computer:

    hostnamectl

  Set the hostname of the computer:

    sudo hostnamectl set-hostname "hostname"

  Set a pretty hostname for the computer:

    sudo hostnamectl set-hostname --static "hostname.example.com" && sudo hostnamectl set-hostname --pretty "hostname"

  Reset hostname to its default value:

    sudo hostnamectl set-hostname --pretty ""

zoxide

zoxide は組み込みコマンド cd の現代的代替物を目指している。 よく移動するパスならば、そのパスの一部を指定すればコマンドが残りを補完して移動するというのが便利だ。

Bash ユーザーならば .bashrc の最後辺りに次のようなコードを仕込んでおくといい:

# Initialize zoxide
[ -x "$(command -v zoxide)" ] && eval "$(zoxide init --cmd cd bash)"

今のところこの設定で無害であるので、実際のところ便利なのだろう。


以上

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment