| date | title |
|---|---|
2025-09-07 |
『入門モダン Linux』読書ノート |
関連サイト:
- 本書目次 https://www.oreilly.co.jp/books/9784814400218/
- 原書 https://modern-linux.info/
- プロジェクト https://github.com/mhausenblas/modern-linux.info
※手書きのメモから書き起こし中。浄書は後ほど行う。
Linux は現代的な分野(モバイル機器、クラウドコンピューティング、IoT, 等々)で動作していたり、使われていたりする。
1990 年代から 2010 年代まで、現在に至る Linux の歴史が要約されている。この前読んだ TAOUP の部分史と言える。
OS を利用することで《リソースを自分で管理する必要がなくなり、ビジネスロジックに集中でき》るようになる。
Linux という言葉は次の二つの意味のどちらかを表すのが通例だ:
- Linux カーネル:すなわちシステムコールとデバイスドライバーの集合。
- Linux ディストリビューション:カーネル、パッケージ管理、関連コンポーネント、等々を一括りにして呼ぶ。
本書ではリソースとはソフトウェア実行の支援のために使用できるすべてのものと定義している。 ハードウェア、ファイルシステム、ドライブ、プロセス、ネットワークデバイス、等々だ。
- コマンド
cat /proc/versionは Linux のバージョンを出力する。 - コマンド
cat /proc/cpuinfoは CPU 情報を出力する。 ちなみにcatではなくbatを使うと少し見やすい。 - コマンド
cat /proc/$$/statusは自プロセスの状態を出力する。
この節の後半の記述がたいせつだ。6 章と 9 章で詳しく議論される。
図 1-1 を頭に入れておく。本書はこの図式の下層から上層に向かって議論を展開する。
Linux は POSIX, System V におおよそ準拠するようにしている。
本書は各章の最後に関連資料を提示しているので、気になるものを閲覧するといい。
- 『Efficient Linux コマンドライン』は邦訳が出版されている。読んだ。
- この中では Advanced Programming in the UNIX Environment が気になる。
カーネル自体は OS ではなく、その中心部分に過ぎない。
三階層構成を意識する。下層から上層に向かって:
- ハードウェア
- カーネル
- ユーザー空間
各層間にはインターフェイスがある。ハードウェアとカーネルの間のインターフェイスはハードウェアごとに異なる。 カーネルとユーザー空間のインターフェイスはシステムコールだ。
TODO: ユーザー空間にはユーザーモードとカーネルモードの二つがある?
- Linux は数多くの CPU アーキテクチャーの上で動作する。
- 現代的環境では BIOS は UEFI に置き換わっている。
- BIOS からハード情報を得る方法はいくつかある:
- コマンド
dmidecode; 環境によってはろくな出力がない可能性がある。 - コマンド
lscpu - 先述した
cat /proc/cpuinfo - コマンド
uname -m
- コマンド
$ uname -m
x86_64TBR
ノート割愛。
ノート割愛。
- Linux カーネルは一枚岩であり、コンポーネント全てが単一バイナリーに収まっている。
- その部品とは、プロセス管理、メモリー管理、ネットワーク、ファイルシステム、デバイスドライバーだ。
プロセス一つは実行プログラム一つに対応するのが一般的だ。スレッドはプロセス内のコードを実行する単位だ。マルチスレッドプログラムを考えるといい。
術語としてのセッション、プロセスグループ、プロセス、スレッド、タスクを理解するのが必須。
- コマンド
ps -jで現セッションにあるプロセス情報を出力する。 - コマンド
ls -al /proc/nnnn/task/nnnnでタスクの情報を出力する。これは詳しく知りたい。
TLB: 仮想メモリーを物理メモリーに変換する仕組み。 頻繁にアクセスされるアドレス変換情報を保持し、ページテーブルへのアクセスを減らすことでシステムの性能を向上させる。
例えば 64 ビット Linux では一プロセス当たり最大 128 TB の仮想アドレス空間、合計約 64 TB の物理メモリー (RAM) の使用が可能。
ファイル /proc/meminfo にメモリー関連の情報がある。
カーネルにおけるネットワークに対する役割は次の三つしかない:
- ソケット
- TCP および UDP
- IP
ネットワークに関してよく使うコマンドは ip だ。
- コマンド
ip linkでネットワークインターフェイスの情報を出力する。 - コマンド
ip routeでルーティング情報を出力する。
- ファイルシステムには
ext4,btrfs, NTFS, etc. などがある。 - VFS はこのような異なるファイルシステムを統一的に扱うための抽象化だ。
詳しくは 5 章で議論される。
デバイスドライバーとは《カーネルで動作する小規模なコード》だ。
デバイスドライバーは (1) カーネルに静的に組み込まれるか、(2) カーネルモジュールとして組み込まれ、必要時に動的にカーネルにロードされる。
- コマンド
ls -al /sys/devicesで Linux システム上のデバイスを確認できる。 - コマンド
mountで「マウントされている」デバイス一覧を出力する。
TODO: これらの出力の読み方がわからない。
- カーネルモードとユーザー空間モードの切り替えは時間的コストがかかる。
- コマンド
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カーネルのバージョンを得るにはコマンド uname -srm を実行するのもいい。
$ uname -srm
Linux 5.15.153.1-microsoft-standard-WSL2 x86_64- 必要に応じてカーネルにロードできるプログラムがモジュールだ。
- コマンド
find /lib/modules/$(uname -r) -type f -name '*.ko*'で利用可能なモジュールを見る。 - コマンド
lsmodでカーネルがロードしているモジュールを見る。このコマンドはファイル/etc/modulesから情報を得る。 - コマンド
modprobeはモジュールを取り扱うのに用いる。細やかなオプション指定が求められる。
システムコール bpf を用いた、Linux カーネル機能を安全かつ効率的に拡張できる Linux 機能だ。
TODO: 何を読みたい?
- CLI の観点からは、Linux と対話する方法は二つある。手動またはスクリプトだ。
- スクリプトを開発したり、保守したりするのに時間をかけ過ぎてはならない。
- 環境変数
TERM - コマンド
infocmp: これは読み方が不明であり過ぎる。 - 新世代のターミナル
$ printenv TERM
xterm-256color自分がどのシェルを使っているかを知る手段を複数知っておく:
file -hecho $0echo $SHELL
以降の記述では、明示がない限り bash が使われるものとする。
おなじみの内容なので割愛。
- 変数は環境変数とシェル変数に分類される。前者は
envで、後者はsetが関係する。 - 表 3-1 は
bash特有の変数一覧だが、https://www.gnu.org/software/bash/manual/html_node/Bash-Variables.html が公式情報だ。
パイプラインで終了ステータスを処理するには変数 PIPESTATUS を用いる。
- コマンド
helpで一覧出力されるコマンド群が Bash 組み込みのコマンドだ。 - POSIX によるならば
whichよりもcommand -vのほうが望ましい。
- バックグラウンド実行をモノにしたい。
- アンドマークを付けて実行したり、
- フォアグラウンド実行してから
C-zを押す。
- ターミナルが閉じても実行を続けさせたいコマンドには
nohupを使え。 - TODO:
disownをちゃんと調べる。
ジョブ制御よりも後述のターミナルマルチプレクサを使え。
よく使われるコマンドには現代的変種が存在する。付録 B を見ろ。
導入した。
導入済み。
いちおうインストールしてチュートリアルも行った。
オプション -g が便利なので、これを単品でプログラム化して欲しい。
導入済み。習得に時間がかかるように思える。
この小節の最後に資料 modern-unix https://github.com/ibraheemdev/modern-unix を紹介している。
シェルが備えている別名機能や略語機能(同じものだ)が基本的だ:
aliasabbr
Emacs 流キーバインドが既定。これで問題ない。
単純なテキスト編集のためだけにテキストエディターを起動するのは非効率的だ。リダイレクト、ヒアドキュメント、各種ツールを上手く使え。
less,batなどのページャーを使え。head,tailなどを用いて必要部分のみを得ろ。
コマンド date の書式を適切に指定すればファイル名の一部として利用可能だ。
次世代の使いやすいシェルを使え。
- 履歴管理不要
- 自動補完
bashから鞍替えする人向けの FAQ がある。
- コマンド
fish_configを実行するとブラウザーが開くらしい。 - Oh My Posh のようなコマンドラインカスタマイズをコードで行っている。
An Introduction to the Z Shell を読めばいい。
- Oil
- murex
- NuShell
- PowerShell
マッスルメモリ=無意識に操作できる程度に染みついている記憶
ターミナルに複数のウィンドウを重ねるツール。
あまり使用するべきではない。
- セッション、ウィンドウ、ペインなどの概念がある。
- コマンドの一例を挙げると
tmux new -s testでセッションtestを起動する。 - キーバインドとしては
C-b wやC-b zのような操作をする。
Windows Terminal のウィンドウでも tmux が使用可能であることを確認した。
- tmuxinator
- Byobu
- Zellij
- dvtm
- 3mux
常用するかどうかは保留するが、tmux を使えるようになってはおきたい。
スクリプトは Bash コードを書くものとする。
- シェルの変数は文字列型であるのが基本だ。
- 配列が使える。
- 本書では言及していないが、連想配列が使える。
割愛。
割愛。
printfはechoよりも移植性が高い。- Bash scripting cheatsheet
- 例の行は
#! /usr/bin/env bashとする。仮想環境を念頭に置いているものと思われる。 - スクリプトファイルに実行権限を付与するには
chmod +xとする。厳密にはchmod 750のほうが良い。次章参照。
次のフラグ設定を自作スクリプトに対して適用したい:
set -o errexit
set -o nounset
set -o pipefailそれぞれ、
- エラーで停止する、
- 未設定変数参照時にエラーとする、
- パイプの一部での失敗を失敗扱いにする、
を指定する。
- ShellCheck
shfmt: 書式整形ツールbats: Bash Automated Testing System; CI 構成用
スクリプト gh-user-info.sh が手許にあるのが望ましい:
https://github.com/mhausenblas/modern-linux.info/tree/main/code/ch03
生産性と作業効率を上げるのがたいせつだ。
- リソース:ユーザーが利用できるハードウェアやソフトウェア部品、言い換えるとファイルを指す。
- 所有権:ファイルを作成したユーザーがその所有者となるのが通例だ。
FreeBSD jail, コンテナー、仮想マシンなどの手法がある。§4.4.2 や 9 章も見ろ。
アクセス制御は二種類に分類される:
- 任意アクセス制御
- 強制アクセス制御
SELinux は後者の実装例の一つだ。政府機関のような安全保障要件が厳格な環境で使用される。使い勝手が落ちるという難点がある。
ユーザーアカウントは Linux では二種類に分類される:
- システムユーザー:デーモンと呼ばれるプログラムは、このユーザー権限でバックグラウンドプロセスとして実行される。
- 一般ユーザー:人間に対応するユーザー。
ユーザー ID (UID) は 32 ビットの数値で表現される。
- UID の値が 0 のユーザーは特別だ。これは
rootとか super user とか呼ばれる。何の制約もなく、あらゆる権限を有する。 - UID の値が 1000 から当分までの値は通常ユーザー。
- 自分の UID はコマンド
id -uで見られる。
ファイルで管理される。
ファイル /etc/passwd がユーザー名簿と考えられる。小さなデータベースのようだ。このファイルのレコードから次の情報を読める(右から左に?):
- ログインシェル
- ホームディレクトリー
- GECOS フィールド(コメントのように用いられるようだ)
- ユーザーの所属する最も代表的なグループの GID
- UID
- パスワード (
x) - 名前
パスワードはファイル /etc/shadow に保存される。※暗号化されている。
ユーザーを追加するにはコマンド adduser を用いる。要特権。
グループという、一人以上のユーザーの集合を実体とする概念がある。
- 普通のユーザーは一つの既定グループに属する(同時に他のグループに属してもかまわない)。
- ファイル
/etc/groupがグループ名簿と考えられる。TODO: 読み方は?
この節の内容はプロ向け。
ユーザー管理が必要なマシンが複数あるなどの場合に、次のような方法を採る:
- LDAP
- ネットワーク経由 (Kerberos)
- 設定管理システム (Ansible, Chef, Puppet, SaltState, etc.)
権限は三種類:
- ユーザー(所有者)
- グループ
- 上記以外
アクセスは三種類(ファイルとディレクトリーで意味あいが変わる):
r: readw: writex: 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 だ。
プロセスは次の四種類の 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
- 伝統的に
rootと関連付けられていた特権は、機能ごとに存在する capability に分解された。 - スレッドごとに capability が存在する。
- capability はシステムレベルのタスクにしか関係しない。
- コマンド
capsh --printはシステムに存在する capability 全てを見る。 - コマンド
grep Cap /proc/$$/statusでコマンド発行元(この場合はシェル)の capability を見る。
プロセスが使用できるシステムコールを seccomp(2) で制限できる。
- ACL はあるユーザーが所属するグループに入っていない(違う)ユーザーやグループに対して権限を与えられる。
- コマンド
grep -i acl /boot/config*の出力のどこかにPOSIX_ACL=Yがあれば、カーネルは ACL をサポートしている。
- 最小権限の原則。必要以上に大きい permission を与えない。必要に応じて
sudoを使え。 - setuid を避けろ。代わりに capability を使え。
- 監査。ログを使えばいつ誰が何をしたかを検証できる。8 章を見ろ。
- capability や seccomp のような高度な機能はコンテナーと関係がある。
- システムに存在するユーザーとファイルをつねに注視しておく必要がある。
- UNIX の「すべてはファイルである」哲学を Linux は継承している。
- ファイルシステムを統一されたインターフェイスと捉えるのが急所だ。
- 階層化
- ディレクトリーと通常ファイル
- コマンド
ls,cd,pwdなどでファイルシステムを探索する - パーミッション(前章を見ろ)
- カーネルに実装されている
術語:ドライブ、パーティション、論理ボリューム、スーパーブロック、inode.
コマンドいろいろ:
lsblk --exclude 7: システムに存在するドライブ、パーティション、論理ボリュームを見る。findmnt -D -t nosquashfs: ファイルシステム一覧を出力する。stat $myfile: 個々のオブジェクトを見る。
表 5-1 の低水準コマンドを全部実行してみるといい。
Linux にはリンクが二種類ある:
- ハードリンク
- シンボリックリンク (
ln -s)
ファイル、ファイルシステムを操作するシステムコールと、操作に対応する処理を実装する個々のファイルシステムの間に挟まる層が VFS だという。
Linux カーネルが定義する VFS 関連データ構造:
inodefiledentrysuper_blockvfsmountfile_system_type- etc.
- PG, VG, LV をおぼえる。
- ボリューム管理ツールは名前が統一されていて簡単に使える。
- PG:
lvmdiskscan,pvdisplay,pvcreate,pvscan. - VG:
vgs,vgdisplay,vgcreate,vgextend. - LV:
lvs,lvscan,lvcreate.
- PG:
コマンド例:
sudo lvscan
sudo vgs
sudo pvdisplay※手許の環境で実行しても何も出力されない。
作成(フォーマット)とマウント(木に挿し込む)の二段階。
mkfs -t ext4 /dev/some-vg/some-lv- 引数なし
mountは一覧出力。 - マウント時にはフォーマットタイプを明示する必要がある。
- マウントを永続化するにはファイル
/etc/fstabに記載する。
- p. 93: ファイルシステムの作成、etc.
- p. 95:
man hierは自分の環境におけるファイルシステムツリーの構成を記述する。
ファイルシステムのふりをして、通常の方法 (ls, cd, cat, etc.) でファイルシステムを操作できるようにしている。
元々の目的はカーネルからプロセス関連の情報を公開し、システムコマンドで使用できるようにすることだった。
cat /proc/self/statusはこのcatプロセスに関するプロセス状態を出力する。cat /proc/self/net/arpは同じく ARP 情報を出力する。
procfs は低レイヤーのデバッグや、システムツールの開発をしているとたいへん便利だ。
sysfs は /sys と対応。
コマンド ls -al /sys/block/sda はブロックデバイス sda の情報を示すファイル一覧を表示する。
devfs は /dev と対応。ブロックデバイス、キャラクターデバイス、特殊デバイスを管理できる。
/dev/null, /dev/random, /dev/tty などでおなじみ。
カタログ的内容につき割愛。
カタログ的内容につき割愛。
高速 I/O と少ないディスク使用量を両立する。CoW の原理は C++ の文字列実装で学んだものと同様のようだ。
何を学びたい?
この章のコードはすべて https://github.com/mhausenblas/modern-linux.info/tree/main/code/ch06/greeter
にある。必要に応じて手許にダウンロードしろ。スクリプトは chmod 750 しておけ。
《アプリを完全に理解するために必要な前提知識(略)をここまでに説明したことで、ようやくアプリに取り組める状態になった》 そうだ。
本章で頻出する術語:
- プログラム:実行ファイルと考えてよいようだ。
- プロセス:メインメモリーにロード済みの実行中プログラムを指す。
- デーモン:サービスをも呼ばれる。バックグラウンドプロセスであることが必要。
- ブート:ハードウェア、OS の初期化を行い、Linux を利用可能状態に至らせるための Linux による一連の手順。
次の五段階に分解して考える:
- UEFI or BIOS
- boot loader
- kernel
- Init
- 他のユーザー空間(シェルなどの初期化?)
カーネルは圧縮されて /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- 元々は
initdに置き換わる init システムだったが、時代が進むにつれて機能がいろいろと追加した。 systemdは依存関係が解決済みのサービスを並列で起動できる。このため起動時間が短縮できる。
systemd を機能や資源により、論理的なまとまりに分解するとこうなる:
| unit | description |
|---|---|
| service | サービス、アプリケーションを管理 |
| target | 依存関係 |
| mount | mount positions |
| timer | cron ジョブなどのタイマー |
| socket | ネットワーク、プロセス間通信ソケット |
| device | udev, sysfs が用いる |
| automount | 名前通り |
| swap | 名前通り |
| path | ファイルやパス監視によるサービス起動 |
| swapshot | システム再構築 |
| slice | cgroup 関連(後述) |
| scope | 外部が作成したシステムプロセスの集合 |
ユニットを systemd に認識させるには、ファイルとして配置する必要がある。サーチパスは複数あるようだ。
systemctl 以外にも systemd を操作するツールがある。
journalctl は systemd が管理するログを閲覧するツールだ。
シェルスクリプト greeter.sh を一時間おきに起動する構成を実習。これはぜひ実施しよう。物資は上記リンクにある。
- 本書の内容でファイル
greeter.{sh,service,timer}を作り、ひとまず任意のディレクトリーに置いてよい。 - 両者を
/run/systemd/systemに置く。コマンドsudo cpで構わないようだ。 - コマンド
systemctl status greeter.timerを実行して確認する。 - ログを見るには
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-2 Linux アプリケーションのサプライチェーンと図 6-3 Linux のパッケージ管理とアプリケーションの依存関係の分類。よく出来ている。 特に、分類は次の三つになる:
- 従来型
- コンテナー
- モダン
この二つのコンビは Red Hat と Debian ベースのシステムから始まった。
- RPM の R は Red Hat を指す。PM は Package Manager の略。
- フォーマットは
.rpmであり、ソースとバイナリーのどちらもアリ。
本書では yum を使った例を示している。すべて root で実行する(実践的には sudo を用いる):
yum search golang
yum install golang
yum info golangDebian で開発されたパッケージマネジャー。
使いやすいラッパーがいろいろとある。私は apt を用いる。これも root で実行するツールだ:
apt search curl
apt install curl
apt show curlプログラミング言語のそれぞれがパッケージマネジャーを独自に用意している。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)
コンテナーとはプロセスのグループであり、Linux の namespace, cgroup, オプションで CoW ファイルシステムを利用してアプリケーションレベルの依存関係の管理を行うものだ。
- 用途は多岐にわたる。
- 著名なコンテナーに Docker が挙げられる。
OCI 準拠のコンテナーを議論する。
プロセスごとにファイルシステム、ネットワーク、ユーザー等の見え方を変更できるような機能だ。
| 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- 資源の使用を制限するためのもの。
- v1 と v2 の二バージョンある。
割愛。
- cgroup v2 には一つの階層しかない。コントローラーすべてが同じ方法で管理する。
- コマンド
systemctl statusで Linux システムの cgroup v2 の木全部を表示できる。 - コマンド
systemd-cgtopで資源使用状況を確認可能(※対話的でない)。
- §5.4.3 を見ろ。
- CoW はビルド時に、パッケージを自己完結した単一ファイルにするのに使用する。
ここから Docker 実習。コンテナーに greeter.sh を入れて実行するものだ:
- ファイル
Dockerfileを作る。 - イメージを作る。
docker build - イメージを見る。
docker images - イメージを実行する。
docker run
ファイル Dockerfile を作る。内容は先述のリンク先にもある。
Docker はコマンド docker run の引数を基に、必要な namespace と cgroup を作成し、イメージ定義のアプリケーションを起動する。
- ファイル
Dockerfileを作る。 - イメージを作る。
sudo docker build -t greeter:1 - イメージを見る。
sudo docker images - イメージを実行する。
sudo docker run greeter:1
割愛。
- Snap
- Flatpak
- AppImage
- Homebrew
※Flatpak は Ubuntu でも利用可能。Homebrew は便利で使っている。
スタータップ、パッケージ管理、コンテナー。
図 7-1 Linux ネットワークの概要:前述の区分どおり、三層に分けて構成要素をまとめてある。下層から上層に向かって順に:
- ハードウェア:NIC, ワイヤレス
- カーネル
- ドライバー
- IP, ICMP
- TCP, UDP
- ソケット
- ユーザー空間:各種アプリケーション(ブラウザー、メール、等々)
図 7-2 通信における TCP/IP 層の連携。ここは四層に分けて考える。下層から上層に向かって順に:
| 層 | 役割 |
|---|---|
| リンク層 | 物理デバイス間でのパケット通信を行う。 |
| インターネット層 | ネットワークによるマシン間のパケット通信を行う。 |
| トランスポート層 | パケットの転送方法、ポートによるマシン上のサービスの認識、データの完成性の確認を行う。 |
| アプリケーション層 | ユーザー向けのツールやアプリケーションを扱う。 |
関連用語:
- イーサネット
- ワイヤレス (Wi-Fi)
- MAC アドレス
- インターフェイス
NIC (Network Interface Controller) は必須のハードウェアだ。カードだ。
- 物理的接続。
- モダンではないようだが、コマンド
ifconfigがわかりやすい。- カードの情報を得る。
- 説明のしやすさのためだけに使う。
- 最近はコマンド
ipを使う。 - どちらの出力にも現れる
UPやRUNNINGなどのフラグの意味を知るには、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:ffARP (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. とエラーで終了すると思う。
- この層ではパケットすべてを独立したものをみなす。
- この層では IP を扱っている。マシンを論理的に見分けるプロトコルだ。
- IP には IPv4 と IPv6 の二種類が存在する。
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/8172.16.0.0/12192.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 foreverinet 127.0.0.1/8のほうがループバックインターフェイスの IP アドレス。inet 172.21.15.53/20のほうがワイヤレス NIC のプライベート IP アドレス。
- IPv6 アドレスは 128 ビット値。16 ビット値をコロンで区切って八つ並べる。十六進数表記で。
- 独特の略記法がある。
- IPv4 との互換性はない。
- RFC 792
- Internet Control Message Protocol.
- とりあえず
pingのプロトコルだと覚えておけばいいだろう。 gpingという、端末にグラフィカルな表示をするツールがある。- IPv6 に対する
pingはping6を使え。
TODO: WSL 環境では IPv6 を使用可能にするのに別途構成が必要らしい。
経路選択処理。システムに届いた個々のパケットをどこに送るかを決める。関連する機能には 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.635msBGP (Border Gateway Protocol): 知っていることがひじょうに重要とまで言っている。自律システム?
ポートは 16 ビット値であり、ある IP アドレスで利用するサービスを識別する。例えば 22 と 80 はそれぞれ SSH と HTTP だ。
ファイル /etc/services にポートとプロトコルの対応が記されている。手許のそれを見たら三百数十行のテキストファイルだった。
コマンド nmap -A localhost でローカルマシンのポートを調べる。
STATEが open なポートを示す。- このコマンドを他のマシンに対して実行してはいけないことになっている。
- Transmission Control Protocol.
- セッションベースのプロトコルであり、パケットの順序性を保証する。エラーが発生すると再送。
- 図 7-5 RFC 793 で定義された TCP ヘッダフォーマットは、オリジナル仕様書では例によってアスキーアートで表現されている。
- TCP 通信は傍受可能、つまりパケットを「捕まえる」ことができ、それを覗くことが可能だ。
- User Datagram Protocol.
- データグラムという形態のメッセージを送信する。
- 図 7-6 RFC 768 で定義された UDP ヘッダフォーマット。データ長は不定のようだ。 これを見てわかるように、これまでのプロトコルヘッダフォーマットと比較してひどく単純だ。
- 《オーバーヘッドが非常に少なく、高いスループットを実現できる》。
- 詳しくは
man 7 udpを見ろ。
- コマンド
ss -sはシステムで使用される TCP ソケット一覧を出力する。 - コマンド
ss -udpはその UDP 版。 - コマンド
lsof -c chrome -i udpを実行すると、Chrome が使っている UDP ソケットの情報を出力する。
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
- gTLD: e.g.
ネームサーバーはレコードを管理する。
- レコードは型、ペイロード、TTL, 等々のフィールドからなる。
- レコードの種類はたくさんある。
A,AAAA,CNAME,NS,PTR,SRV,TXT, etc. - レコードはゾーンファイルと呼ばれるファイルにテキスト形式で表現される。
- ネームサーバーがゾーンファイルを読み込んでデータベースを構築する。
TODO: ここの理解が怪しい。
TODO: p. 157 のコードを模式化すると《図 7-8 ドメイン名空間と FQDN の例》になる?
著者のゾーンには著者がサブドメインを自由に作成可能。それにはゾーンの 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: 114TODO: AUTHORITY SECTION が現れない理由は?
TODO: SRV レコードの話がわからない。
ユーザー空間がアプリケーション層に丸ごと対応すると考えてよい?
- 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 より制限があるという。
SSH は Telnet の安全版と考えられる。後者は通信を暗号化しない。
本書ではクラウド上の仮想マシンへログインする例を示している。真似したいが、次の前提を整えられる環境がない:
- IP アドレスとデフォルトのユーザー名がわかっている
- 秘密鍵ファイルを作成済み
- SCP (Secure Copy Protocol): SSH に基づくファイル転送通信規約。
rsyncはscpより良い。これも SSH を使う。- 転送の宛先は
user@host:形式で指定する特徴が共通している。 - FTP はもう使わないほうがいい。
- AWS は知らない。
- NFS: Network File System
- AWS, Azure など、クラウドプロバイダーが NFS を serve していることが多い。
- SMB (Serve Message Block) や CIFS を使用する。
- Linux とファイル共有をするならば、標準の Samba を用いることになるだろう。
開発者、システム管理者ならば存在は知っておく。
コマンド whois(1) はドメイン名または IP アドレスの所有者、登録者情報を見る。
whois ietf.org のように使う。出力が長い。
- DHCP は IP アドレスをホストへ自動的に割り当てるネットワークプロトコルだ。
- コマンド
dhcpdumpを使えば DHCP パケットをスキャンできる。 E.g.sudo dhcpdump -i $interface_name
割愛。
CLI なら tshark, GUI なら wireshark: 低レベルのネットワークトラフィック解析ツール、パケット表示ツール。
- E.g.
sudo tshark -i $interface_name tcp tcpdumpのほうが古い。
TODO: インストールして使ってみる。
名前だけ挙げると socat, geoiplookup(1), Inlets, BitTorrent. まだ早い。
- TCP/IP
- DNS
- アプリケーション層と高度なネットワーク
本章を読むことで次のことができるようになることを目的とする:
- プロセスのメモリー消費を把握する
- ディスク領域がどれくらい不足するかを予測する
- カスタムイベントの警報を知る(セキュリティー)
観測可能性は事後的であることが通例だが、予測のための観測もある。
図 8-1 は Linux Performance からの引用(英語のほうが見易い)。
TODO: OODA ループ戦略とやらをよく調べる。最初の O が Observe から来ている。
- 観測可能性は見るだけでなく、それから何らかの行動をするということが目的。例:システムの反応が遅い→あるプロセスがメモリーを食いまくっている→殺してみると状況が改善した。
- シグナルの発生源は Linux またはアプリケーションだ。
- 宛先
- テレメトリー
- ログ
- メトリクス
- トレース
- すべてのシステムが生成する基本シグナル
- 人間が扱う
- 構文解析が容易であるテキスト形式
- タイムスタンプが付随する
- メトリクスとは定期的に測定した数値データ(=時系列)を意味する。
- 用途は集計やプロットなど。
メトリクスは次に分類される:
- カウンター:増えるだけのデータ。処理数などを表現する。
- ゲージ:増減するデータ。現在のメモリーサイズ、実行中プロセス数などを表現する。
- ヒストグラム:分布。
- 実行時の情報を動的に収集するもの。
- 用途はデバッグなど。性能評価にも用いられる(§8.4.1 を見ろ)。
表 8-1 一般的なログフォーマット。五種類ある。
- ログにおいてはオーバヘッド(負荷)は避けたい。
- ログ負荷を抑えるツールに
logrotate(8) がある(ログファイルを片付けるツール)。 - ログには DEBUG や INFO などのログレベルという、ログメッセージを度合いで抽出するのに用いられる値を持つことが多い。
自分の環境で ls -al /var/log を実行してみる。
auth.log: ログイン情報btmp: ログイン失敗lastlog: ユーザー全員の最終ログインログ- コマンド
lastlogを実行するといい。
- コマンド
syslog:syslogdの場所(?)
コマンド tail -f $logfile が基本的だ。リアルタイムでログを確認できる。
- RFC 5424 でフォーマットが定義されている。
- ヘッダーフィールド?
syslogdを使ってログを管理するのが一般的だ。次のような新しい実装もある:syslog-ngrsyslog
§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 -fはtail -fの対応物。別窓で実行したい。
手許の環境で試したら、べらぼうに古いログしか閲覧できない。おそらく関連サービスを無効にしている。
監視:システムやアプリケーションのメトリクスを収集するの意。
手法:
- メトリクスを時系列で追跡する
- 指定の条件下で警報を出すように仕掛ける
コマンド 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.019srealにはあまり意味がないという。userとsysがそれぞれユーザー空間とカーネル空間における CPU 時間であることを憶えておけばいい。
コマンド 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.4Mtps欄は一秒あたりの転送量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 などがある。
※この辺から読み流している。
top(1): ヘッダーに概要表示。uptime(1) と同じ情報。CPU, RAM 詳細は表形式。プロセス一覧……。- Windows におけるタスクマネジャーだろう。
- キーバインドを習得する必要アリ。
- 類似物:
htop(1),atop,below(cgroup v2)
- その他
- Glances
- Guider: 少し調べたところ Python 製らしい?
- neoss
- MTR
- どうやって自分で実装するか?
- 自動:開発者がコードを追加する必要がない
- カスタム:メトリクス出力コード片を手動で入れる
- StatsD
- その他、プルベース、スクレイピング
- プロセスの実行を時系列に沿ってキャプチャーすること。
- トレースの情報源は Linux カーネル、ユーザー空間を利用する。
- トレースの使用例
straceなどを使ったデバッグperfを用いたフロントエンドでの性能解析
図 8-5 perf top のスクリーンショット。実行に sudo が要る。
- ePBF が今後のカスタムトレースの主流になるだろう。
- プロファイルングはトレースの特殊な例だ。
pprof(1), Valgrind, flame graph visualizer などのプロファイリングツールがある。
図 8-6 継続的プロファイリングツール parca のスクリーンショット。非常に参考になる例と述べている。
この両者を組み合わせ、長時間メトリクスから高度な observility が得られる。
TOOD: 構成が面倒なのは明らかゆえ、試すのは他を全部やってから最後にする。
- 基本
- ログ
- 監視
- 高度なトピック
IPC があるのは、プロセスが通信し、それぞれの処理を同期し、データを共有するためだ。
- シグナルはプロセスに送られる非同期通知だと考えられる。
- シグナル一覧を確認するには
man 7 signalを見る。 - シグナルのほとんどに対してカスタムハンドラーを定義できる。
表 9-1 一般的なシグナルは七個。SIGQUIT を Ctrl+\ で発生するのは知らなんだ。
コマンド kill はプロセスにシグナルを送るものだ(殺すだけではなかった)。
コマンド kill $pid は kill $pid SIGTERM と同値。
シグナルハンドラーの設定には trap を用いる。
名前付きパイプは 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
...- UNIX ドメインソケットは名前付きパイプとは異なり双方向通信が可能。
- ソケットは IP アドレスやポート番号ではなく、ファイルパスで指示する。
- ドメインソケットはターミナルからというより、プログラムから使用するのが通例。
システムコール socket(2) の第二引数がソケットタイプ:
SOCK_STREAMSOCK_DGRAMSOCK_SEQPACKET
図 9-1 仮想マシンのアーキテクチャ。
- CPU にハードウェア仮想化と可視化機能があることが必要。
- ホストカーネルは構成として KVM (kernel-based virtual machine) を含む。
- 図式右側、四角が縦に積み重なっている。この部分が仮想マシンという理解でいいか?
- VMM (virtual machine monitor) なる仮想デバイスを模倣するソフトウェア (e.g. QEMU, Firecracker) の上にゲストカーネル、ゲストプロセスが乗る。
- ゲストカーネルは仮想マシン上で動作するカーネルの意。
- ゲストプロセスはゲストカーネル上で稼働するプロセスの意。
ネイティブプロセスとゲストプロセスは分離されている。
一般的なハードウェアは仮想化に対応している。KVM を利用可能だ。次のコマンドで検査しろ:
grep 'svm\|vmx' /proc/cpuinfoまたは
lsmod | grep kvm※残念だが WSL Ubuntu では対応していないようだ。
- Firecracker は Rust で書かれた VMM ソフト。
- Firecracker は seccomp フィルターによって使用できるシステムコールを制限してりる。
本書の定義によると《不変性と、自動アップグレード機構を前面に押し出したコンテナベースのディストリビューション》を指す。
TODO: URL 確認
https://github.com/bottlerocket-os/bottlerocket
https://rancher.com/docs/os/v1.x/en/
認証方式 authentication は authorizatin の前提条件。
RFC 4120 で規定されている何か。
図 9-2 Kerberos プロトコルの概念
- PAM: Pluggable Authentication Modules
- モジュール式
pam_localuserpam_keyinitpam_krb5
執筆時点ではまだ主流になっていないだと?
- ソースベースの Linux ディストリビューション。
- Nix パッケージマネジャーは OS 全体を構築する。
- §5.2.3 のようなファイルシステムレイアウトを採用していない。
- 最近は初心者向けのデスクトップ Linux ディストリビューションが多くある。
- WSL を用いて Linux のグラフィカルアプリケーションを実行できる。
Raspberry Pi には Debian ベースの独自のディストリビューションが付属している。
- Gitpod
- GitHub の Codespaces
- IPC
- 仮想マシン
- モダンディストリビューション
- セキュリティー
- その他のモダンまたは将来の話題
包括的なコマンド集が欲しい場合は Linux Cookbook, 2nd Edition を用意する。
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. で終了する。
ログインしているユーザー一覧はコマンド who または w で得る。
- コマンド
top -U $someoneでユーザー$someoneのプロセスにおけるシステムメトリクスを閲覧する。 - コマンド
ps fauxでユーザー全員のプロセス全てを木形式で出力する。 - コマンド
ps -e | grep pythonで Python プロセスの ID を得る。オプション-eはプロセス全部の意。
プロセス ID を知ることで、当該プロセスへシグナルを送信可能になる。
訳者推奨の gstack と pstack はユーザー空間でのスタックトレース表示ツールだそうだが、前者がパッケージ置き場に見つからない。
後者をインストールして適当なプロセス ID で実行すると (No symbols found) と出る。デバッグ用だそうだ。
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 "$@"
}コマンド 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何回見ても忘れる &> と 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- コマンド
timedatectl statusでローカル、UTC, 同期等の情報を得る。 - コマンド
dateで ISO 8601 タイムスタンプを処理できることを覚えておく。
git grep --color-movedは使ったことがない。オプション--color-wordsと併用できるか?git rev-parse HEADで最新コミットの SHA を得る。git describe --tags --abbrev=0で現在のブランチの最新タグの SHA を得る。
最後の二つは別名定義しておいても良いか。
訳者によると apt-get には -y オプションがあるが apt にはないとあるが、事実か?
コマンド yes no で no を無限生成できる。
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本書で紹介しているこのページの一覧のほうが充実している。
以下、実際に試した寸評を記す。
※インストールのために Homebrew を使用可能にしておけ。
bat は cat(1) の構文強調表示&ページャー付きツールとして使える。
- 単純な
cat(1) のほうが望ましい場合が多いゆえ、これをbatで置き換えるようなaliasを定義するには至らない。 - ページャーが既定で動作するのはオプションでオフにできる。E.g.
--pager=never - オプション
-rを使えば出力する行範囲を指示することが可能。head(1) とtail(1) の代用になる。 - よそのコマンドのヘルプを
bat -plhelpにパイプすることでとても見やすくなる。
今のところ利用する可能性が低いのでパス。
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 は dig(1) の現代的代替コマンドだ。
どうもプロジェクトが現時点 (2025-09-03) で活動していないようだ。
fx はターミナルのウィンドウで動作する JSON ビューワーだ。インストールしておいて損はない。
- JSON ファイルを
fxの引数に指定して実行すると専用ページャーが開く。専用キーバインドはオブジェクト閲覧操作を行う。 - オブジェクトの加工出力機能も搭載している。
- ささやかなカスタマイズならば環境変数設定により可能。
fzf は何かの一覧をターミナル画面で対話的に処理、特に選択するための UI と考えられる。
例えば ls, history, git branch, ps などの出力を fzf にパイプで与える用例がある。
- 使いこなせると作業効率が飛躍的に上がる可能性が高い。
- このツールの不思議な名前は fuzzy finder から着想されたらしい。そういえば項目のあいまい指定機能が独特だ。
- Bash では
C-rによる履歴検索が楽になる。 - かなり高級なカスタマイズが可能。
gping は ping(8) の出力がグラフ表示となるツールだ。
- コマンドラインで
gping $hostを単に実行すればいい。 - リアルタイムでプロット描画が更新される。
httpie は curl(1) や wget(1) の代替となる。
- Python 環境が整っていればインストールは容易い。
- インストールすることでコマンド
httpやhttpsが使用可能になる。
$ 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 は JSON コードを生成するツールだ。
- インストールは
apt install joで動作するもので十分使える。 - 例を見ても実践的な用途がわからない。便利でない可能性がある。
本書を読む前にインストール済みだった。JSON コードを部分的に読み取るのに用いることが多い。
rg は grep(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 は systemctl(1) の操作を上述の fzf で行うようにするものだ。
- 先に
fzfを動作可能状態にしておく必要がある。 systemctl(1) を多用する人ならば有用であると考えられる。そうでない人はこのツールと同時に学習するのもいい。おそらくsystemd(1) とも。
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 は組み込みコマンド cd の現代的代替物を目指している。
よく移動するパスならば、そのパスの一部を指定すればコマンドが残りを補完して移動するというのが便利だ。
Bash ユーザーならば .bashrc の最後辺りに次のようなコードを仕込んでおくといい:
# Initialize zoxide
[ -x "$(command -v zoxide)" ] && eval "$(zoxide init --cmd cd bash)"今のところこの設定で無害であるので、実際のところ便利なのだろう。
以上